【问题标题】:Memory management good practices under ARCARC 下的内存管理良好实践
【发布时间】:2013-12-05 14:21:24
【问题描述】:

我的问题更侧重于导航堆栈场景......我有一个,比如说,有几个表格单元格的主视图。每个单元格通过将其推送到导航堆栈来导航到一个新视图,导航堆栈的视图控制器将数据和子视图存储在几个NSMutableArrayNSArray 中。应用程序的常见流程是从主视图控制器到另一个视图控制器来回切换,这是一个常见的场景。考虑到我在 ARC 下,我将不胜感激有关在这种情况下执行的内存管理操作的一些建议:

a) 我应该执行哪些“清洁”人员?是否建议在视图消失时清理数组,还是保留它们以防用户再次导航到视图?

b)关于视图和子视图,当视图消失时我是否也应该“消除”它们?所有这些,包括那些在nib 文件中定义的,还是只有那些我在代码中创建的?

谢谢

【问题讨论】:

  • 你是如何创作和推动的?什么是保留视图控制器(只是导航控制器?)?标准后退按钮?
  • 我在nib 文件中有视图,并且在点击主视图的单元格时我有:MyViewController *myViewController = [[myViewController alloc] init]; [self.navigationController pushViewController:myViewController animated:YES];
  • 我用标准的后退按钮导航回来,是的
  • 我的视图控制器中的集合(NSArrayNSMutableArrayNSDictionary...)都定义为@property (strong, nonatomic)
  • 不,视图控制器使用的集合不应该是弱的。

标签: ios memory-management uinavigationcontroller nsmutablearray automatic-ref-counting


【解决方案1】:

当弹出一个详细视图时,最好的做法是释放内存。如果在您的详细视图控制器中(并且只有那里)您对数据(您的集合)有很强的引用,它们将在弹出时自动释放。

导航控制器保持对推送视图控制器的强引用,当您弹出它时,它会取消该引用。由于唯一对您的集合保持强引用的对象是视图控制器本身,因此它们也会在弹出时被释放。

但是,如果您的一个详细视图控制器中的数据需要时间设置(例如下载)并且用户经常返回和前进到该视图,那么好的做法是保持它在内存中。您可以通过在主视图控制器(表视图控制器)中保持对详细视图控制器的强引用来实现这一点。确保只创建一次重视图控制器并始终推送同一个实例。

如果您保持对繁重的细节视图控制器的强烈引用以使应用程序更快,那么您应该在主表视图控制器的- (void)didReceiveMemoryWarning 中取消该引用。如果视图控制器没有被压入堆栈,内存将被自动回收。 (如果用户想再次输入,请确保重新创建视图控制器)。

对问题 b 的回答不,通常你不会否定你的推荐人。如上所述,如果拥有数组的控制器被释放,它将自动释放所有强属性。

如果您想保留繁重的视图控制器,主表视图控制器中的代码示例:

// MainTableViewController.m

#import "MainTableViewController.h"

@interface MainTableViewController()

@property (nonatomic, strong) UIViewController *myHeavyViewController;

@end

@implementation MainTableViewController

- (UIViewController *)myHeavyViewController
{
    //
    // A getter for the strong myHeavyViewController property. Creates the
    // view controller if needed, or returns it if it already exists.
    //
    if (!_myHeavyViewController) {
        self.myHeavyViewController = ... // Create everything needed
    }
    return _myHeavyViewController;
}

- (void)didReceiveMemoryWarning
{
    //
    // Nil property if we get a memory warning
    //
    self.myHeavyViewController = nil;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath == /* Index path for the heavy view controller */) {

        //
        // self.myHeavyViewController always calls the getter above
        //
        [self.navigationController pushViewController:self.myHeavyViewController animated:YES];
    }
}

@end

【讨论】:

    猜你喜欢
    • 2013-11-19
    • 2021-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-14
    • 1970-01-01
    • 2012-01-15
    • 2013-01-17
    相关资源
    最近更新 更多