开始我正在构建一个应用程序来学习Objective-C的基础知识。如果有任何不清楚的地方请告诉我,我会编辑我的问题。
该应用程序应该具有下一个功能。 执行应用程序时打开相机预览。在顶部有一个按钮,可以转到TemplateController,用户可以在其中选择要从UICollectionView中选择的帧数组。用户选择模板并返回到相机预览。用户拍摄照片,所选帧的图片显示在PreviewController中。如果用户不喜欢该框架并想要将其切换为另一个框架。 PreviewController顶部有一个按钮,可以转到TemplateController,选择框架并再次返回到带有新框架的PreviewController。
我不想每次为框架创建一个对象。我希望AppDelegate持有该对象。为了让它保持活力?(抱歉,英语不是我的母语)。
我在想使用NSUserDefaults但是我真的想用AppDelegate来做。所以在这一点上NSUserDefaults不是一个选择。
现在,我正在使用带有导航控制器的故事板。屏幕截图可在此处获得 现在,当我从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。如果我在拍完照片后选择了画面,则会显示。
答案 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];
}
}
要更多地解决这个问题:
更改显示视图控制器的代码:
到
- (IBAction)showFrameSelector:(id)sender
{
[self performSegueWithIdentifier:@"SegueTitle"];
}
将您的数据对象添加到目标视图控制器,如prepareForSegue中所述,您将处于良好状态。然后使用委托方法捕获从模板返回的任何数据(只需将数据作为属性添加到控制器,你应该是金色的)
你可以在Xcode的实用程序项目模板中看到这个委托的更好例子(我只是将其键入...)我希望这些信息有所帮助。您可以在这些资源上获取更多信息,也可以通过搜索Google和SO进行iOS委派: