使用AppDelegate来回传递数据

时间:2013-11-29 03:54:55

标签: objective-c appdelegate

开始我正在构建一个应用程序来学习Objective-C的基础知识。如果有任何不清楚的地方请告诉我,我会编辑我的问题。

该应用程序应该具有下一个功能。 执行应用程序时打开相机预览。在顶部有一个按钮,可以转到TemplateController,用户可以在其中选择要从UICollectionView中选择的帧数组。用户选择模板并返回到相机预览。用户拍摄照片,所选帧的图片显示在PreviewController中。如果用户不喜欢该框架并想要将其切换为另一个框架。 PreviewController顶部有一个按钮,可以转到TemplateController,选择框架并再次返回到带有新框架的PreviewController。

我不想每次为框架创建一个对象。我希望AppDelegate持有该对象。为了让它保持活力?(抱歉,英语不是我的母语)。

我在想使用NSUserDefaults但是我真的想用AppDelegate来做。所以在这一点上NSUserDefaults不是一个选择。

现在,我正在使用带有导航控制器的故事板。屏幕截图可在此处获得 enter image description here 现在,当我从TemplateController传递到我的PreviewController时,我的代码如下所示:

从MainController或PreviewController到达TemplateController

- (IBAction)showFrameSelector:(id)sender 
{
    UIStoryboard *storyboard;
    storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard_iPhone" bundle:nil];
    TemplateController *templateController = [storyboard instantiateViewControllerWithIdentifier:@"TemplateController"];
    templateController.frameDelegate = self;
    [self presentViewController:templateController animated:YES completion:nil];
}

将数据从TemplateController传递到其控制器的命运(MainController或PreviewController)

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    _selectedLabelStr = [self.frameImages[indexPath.section] objectAtIndex:indexPath.row];
    [self.collectionView deselectItemAtIndexPath:indexPath animated:NO];

    [self dismissViewControllerAnimated:YES completion:^{
    if ([self.frameDelegate respondsToSelector:@selector(templateControllerLoadFrame:)]) 
    {
            [self.frameDelegate performSelector:@selector(templateControllerLoadFrame:) withObject:self];
    }
    }];
}

这会在PreviewController

中加载选定的帧
- (void)templateControllerLoadFrame:(TemplateController *)sender
{
    UIImage *tmp = [UIImage imageNamed:sender.selectedLabelStr];
    _frameImageView.image = tmp;      
}

我的问题是,我不太清楚我在AppDelegate上做了哪些更改(现在没有改动)。实现这一目标的最佳方法是什么? 主要问题是在拍摄静止图像之前选择了Tamplate。如果我在拍完照片后选择了画面,则会显示。

1 个答案:

答案 0 :(得分:1)

我不确定我理解你的问题。将对象填充到app delegate解决方案可能不是最好的方法。实际上我相信你应该看一下Apple用来在视图控制器之间进行通信的委托模式。请注意,您似乎已经完成了委托模式的一半。例如,您将PreviewController设置为TemplateController的frameDelegate。

所以我认为你有类似的东西将TemplateController中的信息传递回PreviewController。请注意,我已经包含了对segue的准备,因为这是推送数据对象的常用模式(如果你将一个segue从PreviewController连接到TemplateController并在你的动作方法中调用performSegueWithIdentifier:@“SegueTitle”,它将被调用) 。使用“templateControllerDidFinish”委托方法是一种常用模式,用于在关闭时从TemplateController推送信息。

TemplateController.h

@class TemplateController;
@protocol TemplateControllerDelegate <NSObject>
-(void) templateControllerDidFinish :(TemplateController*)controller;
@end

@interface TemplateController : UIViewController 
@property (nonatomic, weak) id <TemplateControllerDelegate>delegate;
...
@end

TemplateController.m
 //! The internals for this method can also be called from wherever in your code you need to dismiss the TemplateController by copying the internal 
-(IBAction)doneButtonAction:(id)sender
{

    __weak TemplateController*weakSelf = self;
    [self dismissViewControllerAnimated:YES completion:^{
        [self.delegate templateControllerDidFinish:weakSelf];
    }];
}

PreviewController.h

#import "TemplateController.h"

@interface PreviewController<TemplateControllerDelegate>
...
@end

PreviewController.m

@implementation
...
-(void) templateControllerDidFinish :(TemplateController*)controller
{
    self.dataProperty = controller.someImportantData;
    ...
}

...

-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
    if ( [[segue identifier]isEqualToString:@""] ) 
    {
         TemplateController *tc = [segue destinationViewController];
         tc.delegate = self;
         tc.data = [someDataObjectFromPreviewController];
    }
}

要更多地解决这个问题:

  1. 将PreviewController中的segue添加到TemplateController (按住Ctrl键并从预览视图控制器拖动到模板控制器 在文档大纲模式中)
  2. 在身份检查器中命名segue标识符
  3. 更改显示视图控制器的代码:

    • (IBAction为)showFrameSelector:(ID)发送方 { UIStoryboard *故事板; storyboard = [UIStoryboard storyboardWithName:@“MainStoryboard_iPhone”bundle:nil]; TemplateController * templateController = [storyboard instantiateViewControllerWithIdentifier:@“TemplateController”]; templateController.frameDelegate = self; [self presentViewController:templateController animated:YES completion:nil]; }
  4. - (IBAction)showFrameSelector:(id)sender 
    {
        [self performSegueWithIdentifier:@"SegueTitle"];
    }
    

    将您的数据对象添加到目标视图控制器,如prepareForSegue中所述,您将处于良好状态。然后使用委托方法捕获从模板返回的任何数据(只需将数据作为属性添加到控制器,你应该是金色的)

    你可以在Xcode的实用程序项目模板中看到这个委托的更好例子(我只是将其键入...)我希望这些信息有所帮助。您可以在这些资源上获取更多信息,也可以通过搜索Google和SO进行iOS委派:

    Concepts in Objective C (Delegates and Data Sources)

    Cocoa Core Competencies