通过prepareForSegue:sender传递数据:并将初始值分配给出口

时间:2014-03-05 17:10:28

标签: ios objective-c storyboard

我正在使用现有代码,我看到我们使用performSegueWithIdentifier:sender:推送一些viewController,然后我们将数据传递给目标viewController:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

  if ([segue.destinationViewController isKindOfClass:[DetailsViewController class]]) {

    DetailsViewController *detailsVC = (DetailsViewController *)segue.destinationViewController;
    detailsVC.detailsData = someData; 
  }

然后想象我们在destinationViewController中有一个自定义的setDetailsData setter:

- (void)setDetailsData:(NSDictionary *)detailsData {

  _detailsData = detailsData;
  // other data customisation stuff

  // Then we need to assign initial values to outlets
  // The view is not loaded yet, so we are forcing to initialise this view. This will result in viewDidLoad being called 
  self.view.userInteractionEnabled = YES;

  // Set outlet values
  self.firstNameLabel.text = [_detailsData …];
  self.lastNameLabel.text = [_detailsData …];
}

在prepareForSegue内执行setDetailsData:时,尚未调用destinationViewController的有趣部分viewDidLoad。所以我们不能为这些出口分配值,因为它们尚未初始化(零)。因此,为了使其工作,有一点点黑客:

self.view.userInteractionEnabled = YES;

这会强制初始化视图和插座。我同意,拥有这样的自定义设置器既可以用于内部数据的定制,也可以分配出口很方便(一切都在一个地方),但我担心这会破坏正常的视图初始化流程。我们应该只传递数据。应在viewDidLoad方法中单独分配出口的值。你对此有什么看法,这是正常的吗?我无法在Apple文档中找到任何限制,但仍然对此表示怀疑。

3 个答案:

答案 0 :(得分:1)

请记住将您的财产设置为强大:

@property (strong, nonatomic) NSDictionary * detailsData;

并在viewDidLoad中进行UI更新。

答案 1 :(得分:1)

我不喜欢它,但是如果它有效的话就可以了!

我的意思是,你的代码工作且没有错误(假设它不是)的事实证明技术是解决这个小问题的可行方法。

但另一方面,这是我个人的观点,它使代码看起来很脏。当你看到那行代码时

self.view.userInteractionEnabled = YES;

你会认为“哦,这必须使用户能够与UI进行交互,默认情况下必须禁用它”,但是没有,这是一个初始化UI的黑客行为。因为我们经常复制粘贴我们自己的代码,所以我们养成了一个坏习惯。

答案 2 :(得分:0)

由于您已经保存了对详细信息数据的引用,我的偏好(以及“规范”)将视图初始化(self.firstName.test ....)移动到viewDidLoad中。这样你就可以保证视图已被加载但尚未显示并且你不再依赖“self.view.userInteractionEnabled = ...”的副作用。如果你真的坚持在那里做,至少使用“if(!self.isViewLoaded)[self loadView]”