Objective c 使用AppDelegate来回传递数据

Objective c 使用AppDelegate来回传递数据,objective-c,appdelegate,Objective C,Appdelegate,首先,我正在构建一个应用程序来学习Objective-C的基础知识。如果有任何不清楚的地方,请让我知道,我将编辑我的问题 该应用程序应该具有下一个功能。 执行应用程序时打开相机预览。顶部有一个按钮,用于转到TemplateController,用户可以在其中选择要从UICollectionView中选择的帧数组。用户选择模板并返回相机预览。用户拍摄一张照片,选定帧的照片显示在PreviewController中。如果用户不喜欢该帧并希望将其切换为另一帧。PreviewController顶部有一

首先,我正在构建一个应用程序来学习Objective-C的基础知识。如果有任何不清楚的地方,请让我知道,我将编辑我的问题

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

我不希望每次都为帧创建对象。我希望AppDelegate保存该对象。让它活下去?(对不起,英语不是我的母语)

我想使用NSUserDefaults,但我真的想使用AppDelegate。因此,在这一点上,NSUserDefaults不是一个选项

现在,我正在使用带有导航控制器的故事板。这里有一个截图 现在,当我从TemplateController传递到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传递到其控制器的destiny(MainController或PreviewController)

这将在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];
    }
    }];
}
- (void)templateControllerLoadFrame:(TemplateController *)sender
{
    UIImage *tmp = [UIImage imageNamed:sender.selectedLabelStr];
    _frameImageView.image = tmp;      
}
我的问题是,我不太清楚我必须对AppDelegate做什么更改(它现在还没有被触及)。实现这一目标的最佳方法是什么?
主要问题是在拍摄静止图像之前,何时选择Tamplate。如果我在拍照后选择了相框,它就会显示。

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

因此,我认为您应该有如下内容将信息从TemplateController传输回PreviewController。请注意,我已经包含了prepare for segue,因为这是向前推送数据对象的常见模式(如果将segue从PreviewController连接到TemplateController,并且在操作方法调用PerformsgueWithIdentifier:@“SegueTile”中,将调用它)。使用“TemplateControllerdFinish”委派方法是一种常见的模式,用于在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];
    }
}
如PrepareForegue中所述,将数据对象添加到目标视图控制器,您将处于良好状态。然后使用delegate方法捕获从模板返回的任何数据(只需将数据作为属性添加到控制器中,您就可以了)

您可以在Xcode中的实用程序项目模板中看到这种委托的更好示例(我刚刚键入了…),希望这些信息能有所帮助。您可以在这些资源中获得更多信息,也可以通过搜索Google等获取iOS授权:


NSUserDefaults用于存储特定于应用程序的设置(例如,上次更新的时间、用户关闭同步功能等(并且不存储任何敏感信息))。如果要将“对象”存储在AppDelegate中,则必须使用@chuthan20创建一个委托。在这种情况下,AppDelegate将接收和发送数据。我是否需要创建一个代理作为发件人,并在TemplateController中创建另一个代理作为发件人?应用程序代理只是一个对象。您可以通过在自己的类中采用UIApplicationLegate协议来定义它,然后在
main
中创建类的实例。完成后,您可以从UIApplication获取应用程序委托的地址,并访问其中的属性和方法。这是存储全局引用数据的好地方。(从这个角度来看,它只是另一个对象,尽管你可以从应用程序中的任何位置获取它的地址。)你既不应该使用
NSUserDefaults
也不应该使用
AppDelegate
在视图控制器之间传递数据。看看如何在视图控制器之间传递数据。@Sebastian是正确的。这是最受鼓励的方法,如果你想要一个好的架构,你应该遵循它。你所做的就是我的代码现在看起来如何。非常相似。现在,当用户进入TemplateController时,选择一个帧,然后返回主控制器,捕捉图片,当我尝试将该值传递给PreviewController时,该值消失。所以我想让它保持活动状态,并在AppDelegate中创建一个引用,以便其他控制器也可以访问它。@Edu我想我现在明白了。在我们打破正确的模式之前,我可以建议我们找出如何保留对PreviewController的引用吗?再次检查我的代码,您将看到它意味着一个连接两个视图控制器的序列。您的图像显示您没有安装segue。这样做可以解决当前的问题,而不会造成更大的问题。如果我们能帮助的话,我宁愿不要传递一个不好的实践。我更新了部分代码。如果您想查看.h文件的组织方式,我可以编辑。我没有在TemplateController中使用segue,出了点问题。调试时,所有内容都在正确的位置,但帧没有显示,因此无法到达TemplateController,我使用以下行(解决了问题)情节提要=[UIStoryboard情节提要,名称:@“MainstryBoard_iPhone”bundle:nil];TemplateController*TemplateController=[storyboard InstanceDeviceController的标识符:@“TemplateController”]@Edu我也这么想还有edite
- (IBAction)showFrameSelector:(id)sender 
{
    [self performSegueWithIdentifier:@"SegueTitle"];
}