从iOS 6开始,展开的segue可用于向上导航场景层次结构。我试图决定将数据传递给父视图控制器的更清洁/更好/首选/更可维护的方法。从技术角度来看,有一些问题可以解决这个问题(例如“如果我有一个放松,我还需要一个代表”)但我找不到太多可以解决利弊的问题。
选项1:使用代表。
选项2:使用展开segue
Exit
并将segue命名为performSegueWithIdentifier:sender
returnFromSegueName
(链接到该segue的用户名为方法)从孩子那里获取数据。canPerformUnwindSegueAction:fromViewController:withSender
来实现
总的来说,代表们感觉更干净,但也许过时了。我倾向于朝那个方向倾斜吗?
答案 0 :(得分:11)
我现在意识到这不是一个真正的问题,除了说这两种方法都没有错 - 它们都有其优点和缺点。在解决了一周并完成了关于这个主题的更多阅读之后,我至少可以量化为什么你可能想要使用unwind segue或者委托来在视图控制器之间工作。
两种模型大致相同(松散)耦合。在引擎盖下,展开segue只是一个代表,iOS已经完成了为您配线的工作。对于代理人,父母知道并遵守子协议。对于展开segue,父必须连接到故事板上的子节点以进行展开,并且需要知道子节点的属性以提取返回数据。但是,如果您是新来的代理人并且只想从子视图中获取一些数据,则展开segue可能不如使用具有委托的协议那样令人生畏。
如果子到父交互的唯一目的是返回数据,则展开segues只是一个不错的选择。似乎没有办法取消正在进行的展开segue。因此,如果父级必须进行任何数据验证,或者子级需要与父级进行多次交互,则执行此操作的唯一方法是使用委托,其中可以将多个方法调用回父级。
如果返回的数据的类型或其他方面发生变化,则更新展开segue会更容易,因为您只需要更新展开segue中的代码以查看新属性。对于协议/委托方法,您必须更新子级中的协议和父级中的实现。但是,unwind segue的简单性是由于您没有编译器检查您的合同(协议)而您可能很容易错过需要更新的父视图控制器中的位置。
没有一个。您选择哪种方式取决于您的数据需求,协议的舒适程度(乍一看它们看起来比它们应该更加令人生畏),应用程序的复杂性以及长期维护需求。
就我的目的而言,我最后使用了代表,因为在某些情况下,我的孩子不得不多次回电给父母。但是,在我有许多数据要传回来的情况下,我采用了从unwind segue中学到的东西,并简单地使用了父级可以从中提取所需信息的子属性。我还使用它作为父方向孩子提供错误信息的便捷路径。为了与编程合作伙伴保持一致,我不会在程序中混合和匹配unwind segue与代表,但如果你愿意的话,没有理由你不能这样做。
答案 1 :(得分:7)
我对故事板非常怀疑,但我决定潜入并在新项目中使用它们。我很惊讶你可以轻松地在两个视图控制器之间进行通信。执行performSegueWithIdentifier时,您将获得新ViewController的句柄。您可以非常干净,漂亮地在新的viewController中设置所需的任何公开属性。
以下是一个例子:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
Student *student = [self.students objectAtIndex:indexPath.row + [self rowAdjuster]];
[[segue destinationViewController] setStudent:student];
}
}
非常好,整洁。没有您需要跟踪或维护的特殊协议。
然后回来(我的IBAction连接到我的详细视图中的按钮)您可以再次获得对要返回的viewController的干净引用,并对该viewController进行操作。
- (IBAction)returnWithStudent:(UIStoryboardSegue *)segue {
UIViewController *vc = [segue sourceViewController];
if ([vc isKindOfClass:[ AddStudentViewController class]]) {
AddStudentViewController *addViewController = (AddStudentViewController *)vc;
if (addViewController.student != nil) {
if ([addViewController hasTakenPhoto]) {
[PhotoHelpers saveImageForStudent:addViewController.student];
}
[StudentController updateStudent:addViewController.student];
}
}
}
segue逻辑控制也很好。可以在shouldPerformSegue中执行逻辑检查,这非常方便。
我已经看到很多垃圾代码使用了“将某些内容发送给调用者”的协议,这些协议在耦合类时非常差。它做了三向安排 - viewController1 - >协议 - > viewController2,而segues是viewController1-> viewController2的一个很好的安排。
segue是一种干净而独特地结合这两个类的好方法。我强烈推荐它。