故事板和自定义初始化

27

我最近尝试使用Xcode中的MainStoryboard.storyboard进行工作,目前进展顺利,我想知道为什么以前从未使用过它。在尝试一些代码时,我遇到了一个障碍,不知道该如何解决。

当我使用自定义init在ViewControllers类中声明并alloc和init一个新的ViewController时,我会像这样做:

ViewController *myViewController = [[ViewController alloc] initWithMyCustomData:myCustomData];

之后我可以做类似这样的事情:

[self presentViewController:myViewController animated:YES completion:nil];

当我使用故事板进行工作时,我学到切换到独立的ViewController需要一个标识符。

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
ViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:@"MyViewControllerIdentifier"];
[self presentViewController:myViewController animated:YES completion:nil];

在使用故事板(storyboard)的同时如何仍然使用自定义初始化(custom initialization)来创建myViewController?

只需像这样做是否可行:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
ViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:@"MyViewControllerIdentifier"];
myViewController.customData = myCustomData;
[self presentViewController:myViewController animated:YES completion:nil];




//MyViewController.m
- (id) initWithMyCustomData:(NSString *) data {
if (self = [super init]) {
    iVarData = data;
}
return self;
}
3个回答

21

我会创建一个方法来进行自定义数据加载。

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MyViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:@"MyViewControllerIdentifier"];
[myViewController loadCustomData:myCustomData];
[self presentViewController:myViewController animated:YES completion:nil];
如果你的initWithCustomData方法只是用于设置一个实例变量,那么你可以手动设置它而不需要使用自定义初始化方法或额外的方法:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
MyViewController *myViewController = [storyboard instantiateViewControllerWithIdentifier:@"MyViewControllerIdentifier"];
myViewController.iVarData = myCustomData;
[self presentViewController:myViewController animated:YES completion:nil];

17
谢谢。看起来很疯狂,苹果不提供在Storyboards中创建适当的自定义init方法的方式。 - jowie
2
我不确定为什么有人会说:“如果你的initWithCustomData方法只是设置一个实例变量,那么你应该手动设置它(不需要自定义初始化或额外的方法)”。苹果没有提供这样的文档,因此我建议读者将此声明视为纯粹的意见而非必须遵循的规则。在iOS中,有很多初始化程序甚至只需要一个参数。 - zumzum
@zumzum苹果在其示例代码中确实使用了在“prepareForSegue:sender:”方法中设置变量的做法。请参见EKReminderSuite示例项目中的“AddTimedReminder.m”文件以获取示例。 - Addison
@zumzum 是的,这是我的观点。如果只是为了设置一个实例变量而创建一个方法似乎没有意义,因为它可以直接设置。显然有一些初始化程序只需要一个参数;然而,在这种情况下,如果创建自定义 init 是一项挑战,我认为这是一个更简单的攻击角度。 - carloabelli

17

你可以在-init方法中实例化视图控制器。

 - (instancetype)init
 {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];

   self = [storyboard instantiateViewControllerWithIdentifier:@"MyViewController"];

   if(self)
   {
    //default initialization

   }
   return  self;
 }

并且在你的自定义初始化方法中

 - (instancetype)initWithImages:(NSArray *)images
 {
   self = [self init];

   if(self)
   {
     self.images = images;
   }

   return  self;
 }

很遗憾,这个解决方案不再符合“风水”了,因为你的-(instancetype)init没有调用超类指定的初始化程序。 - Over Ukraine

3

My version:

- (instancetype)initWithData (NSArray *)someData
 {
    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]];

   self = [storyboard instantiateViewControllerWithIdentifier:@"MyViewController"];

   if(self)
   {
    //default initialization

   }
   return  self;
 }

...一个构造器初始化值的简写 ;)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接