【问题标题】:Subview management within master/detail view in iOS (with ARC)iOS 中主/详细视图中的子视图管理(使用 ARC)
【发布时间】:2012-10-31 18:20:45
【问题描述】:

我的应用有一个主从控制器。主控制器是一个 UITabBarController,每个选项卡都是一个 UITableViewController,包含不同类型的数据。

我计划在主详细视图上显示一个主标题/图像,但随后需要向主详细视图添加不同的子视图,以根据我使用的选项卡详细说明特定信息。

我目前正在我的

中添加相关的子视图

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

函数如下:

UIViewController *subview = [[UIViewController alloc] initWithNibName:@"ItemNotFoundViewController" bundle:nil];
subview.view.frame = CGRectMake(20, 160, subview.view.frame.size.width, subview.view.frame.size.height);  
[self.detailViewController.view addSubview:subview.view];

但是,我认为这是一种糟糕的处理方式 - 每次有人单击表格单元格时,都会在先前添加的子视图堆栈顶部抛出另一个子视图,从而产生内存问题。

我想知道的是,ARC 会为我解决这个问题吗?我的方法可以通过吗?并且即使可以通过,有没有更好的方法来做到这一点?

【问题讨论】:

    标签: ios uiview master-detail


    【解决方案1】:

    首先,不。 ARC 不会为您处理这些问题。这样做不是目的,即使它是,它怎么知道你不再想要以前添加的子视图? 您必须自己删除这些子视图,然后然后 ARC 将负责解除分配它们(如果没有其他对它们的引用)。

    无论如何,这不是您应该使用UISplitViewController(主-细节视图控制器)的方式。正如您所注意到的,拆分视图控制器处理其他两个视图控制器。 master- 和 detailViewController。在大多数情况下,主视图控制器在应用程序运行时不会发生变化(它的内容会发生变化,但通常由分配为 masterViewController 的 UINavigationController 之类的容器视图控制器处理),但详细视图控制器会。

    与其向现有的 detailViewController 添加子视图,不如将其替换为新的。因此,您应该为要在详细信息部分中显示的所有视图控制器创建单独的 XIB(显然您已经完成了)。并将您的代码修改为

    self.detailViewController = newDetailViewController; //newDetailViewController would be the vc you called subview in your code
    

    而不是

    [self.detailViewController.view addSubview:subview.view];
    

    编辑:请注意,这假定您的 detailViewController 属性在您设置它的值时会做“正确的事情”。默认情况下,UISplitViewController 只有一个名为viewControllers 的属性,它是一个NSArray,其中第一个对象是masterVC,第二个是detailVC。

    查看MultipleDetailViews 以了解如何管理它的示例。

    由于您希望在所有详细视图控制器中都有一个标题视图,因此您有多种选择来实现它(这可能适用于您的情况,也可能不适用,具体取决于您的设计):

    • 将标题视图添加到每个详细信息 vc 的 XIB 中
    • 不要为所有 detailVC 创建许多 XIB,而是创建一个新的自定义 UIViewController 子类,它会根据您提供的一些参数修改其内容,即用户点击了哪个 tableViewCell
    • 创建一个自定义容器视图控制器来管理两个子视图控制器,一个用于标题,一个用于上面的内容。

    更多关于UISplitViewController和自定义容器视图控制器的信息,请参考:

    View Controller Basics

    Creating Custom Container View Controllers

    【讨论】:

    • 好的,我正在关注 - 但是,我将代码 [self.detailViewController.view addSubview:subview.view]; 更改为 [self.detailViewController setView:subview.view]。这样做是否有效,而不是重新分配整个控制器?
    • 也许有,也许没有。我知道这是一个糟糕的答案,但事实是,你真的不应该那样做。正如 Apple 在多个场合明确指出的那样:视图控制器拥有并管理它的视图,不要拿走它的视图,否则会发生坏事(即抓住它并将其放入另一个视图控制器)。花点时间阅读UISplitViewController的正确用法,从长远来看,它将为您节省很多麻烦。苹果还表示,当你创建一个他们称之为不一致的层次结构时,他们可能会在未来开始抛出异常。
    • 好的。我问的唯一原因是因为在更换整个控制器时,我的视图拒绝更新,即使在执行[subviewController setNeedsDisplay] 时也是如此。执行我刚才询问的操作实际上正确地刷新了视图。
    • 其实我不够精确,你不能只替换那条线,一切都很好。我已经编辑了我的答案,并添加了一个指向 Apple 示例项目的链接,其中介绍了如何管理不同的详细视图控制器。同样,如果您的细节视图控制器没有做太多花哨的事情,那么两个创建一个自定义视图控制器子类来管理不同的细节视图可能就足够了。 XCode-Template Master-Detail-Application 就是这样做的。也许你也看看那个。
    【解决方案2】:

    不,ARC 不会为您处理这个,因为 detailViewController.view 将保留对其子视图的引用。如果不更多地了解您正在使用这些视图做什么,很难说哪种方法是最好的。最好只展示新的视图控制器——如果你没有指向它的属性,它会在它被解除后被释放。

    【讨论】:

    • 我基本上每个选项卡只有两个视图 - 一个是“数据库中未找到项目”视图,另一个是详细说明有关该项目的所有信息的视图。这些视图适合作为我的主要详细视图的子区域的主要内容区域。
    猜你喜欢
    • 1970-01-01
    • 2012-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多