我有一个UITableView,其委托和数据源位于不同的文件中。点击一行时,在tableView:didSelectRowAtIndexPath:
中,应该在堆栈上推送新的视图控制器。由于NSObject文件(包含UITableView委托和数据源)没有presentViewController:animated:completion:
,因此我无法推送新的视图控制器。
我认为有两种方法可以解决这个问题。
将表视图的视图控制器(RootViewController
)的属性添加到NSObject文件,并在初始化对象时将该属性设置为等于视图控制器。这样我就可以在tableView:didSelectRowAtIndexPath:
[self.rootVC presentViewController:detailVC animated:YES completion:nil];
我还可以在NSObject文件中添加一个委托,该文件在RootViewController
中执行更改视图控制器的逻辑。
@protocol YBMatchesTableViewDelegateAndDataSourceDelegate
@optional
-(void)rowTapped;
@end
@property(nonatomic,assign)id delegate;
tableView:didSelectRowAtIndexPath:
[self.delegate rowTapped];
。最后,在RootViewController中。
-(void)rowTapped {
DetailViewController *detailVC = [[DetailViewController alloc] init];
[self presentViewController:detailVC animated:YES completion:nil];
}
什么行不通:
[[RootViewController new] presentViewController:detailVC animated:YES completion:nil];
RootViewController
进行子类化,并将tableview的委托和数据源放在那里。 两者都说它不在视图层次结构中。 Warning: Attempt to present <DetailViewController 0x109123ff0> on <RootViewController: 0x10912aef0> whose view is not in the window hierarchy!
您更喜欢哪一个?或者我应该不使用哪一个?我倾向于去代理,因为第一个给我另一个属性/对象。
答案 0 :(得分:1)
我可能会选择选项2 。这意味着您的委托和数据源不需要保持对viewcontroller的引用,只是为了它可以呈现另一个viewcontroller。这也是一个额外的责任分离 - 您的委托/数据源仅负责管理tableview的数据,不用于在用户选择某些内容时执行UI功能/导航。
通过实施代理,您的YBMatchesTableViewDelegateAndDataSource
仍然是数据。它只是报告用户何时选择了一段数据。然后,您的viewcontroller可以决定如何管理视图以处理它。
我建议您重命名rowTapped
方法。我会使它更具描述性,并且根据您的设置,您可能希望传递一个参数,以便您的viewcontroller知道它需要显示哪些内容。类似的东西:
- (void)userDidSelectMatch:(YBMatch *)match;
或类似的东西(只是猜测你的数据结构),可能会更有意义吗?