【问题标题】:UIViewController not realised with ARC and a navigation controllerUIViewController 没有用 ARC 和导航控制器实现
【发布时间】:2013-11-14 19:26:06
【问题描述】:

我有一个导航控制器,它加载一个 UITableviewcontroller (DOArticleListViewController):

- (void) showList: (NSFetchedResultsController*) list title:(NSString*) title {
    DOArticleListViewController* listView = [[[self navigationController] storyboard] instantiateViewControllerWithIdentifier:@"DOArticleListViewController"];
    [listView setObjects:list];
    [listView setViewTitle:title];
    [[self navigationController] pushViewController:listView animated:YES];
}

当我点击 DOArticleListViewController 中的“后退”按钮时,视图没有被释放(没有 dealloc/viewDidUnload),并且每次我前进和前进时内存使用量都会增加。

可能是什么原因,或者我该如何强制它释放? 我可能与“NSFetchedResultsController”有关,因为我最近才搬到 ARC。

TableViewController 的声明是:

@interface DOPrototypeListViewController : DOPrototypeViewController <NSFetchedResultsControllerDelegate, UITableViewDelegate> {

    IBOutlet UITableView * _tableView;

    int _cellHeight;

@protected
    NSFetchedResultsController* _objects;   
    NSString* _cellIdentifier;

    bool _commonId;
    int _sectionItemsSkipped;
}

@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSFetchedResultsController* objects;

- (NSIndexPath*)calculateObjectIndexPath:(NSIndexPath*) indexPath;
- (NSIndexPath*)calculateTableIndexPath:(NSIndexPath*) indexPath;

@end

我将列表声明为强,就好像我使它变弱一样,NSFetchedResultsController 在我去后续detailViewController 时寻找对象时被卸载。

编辑: 我想我可能有一个更根本的问题,因为分析似乎没有对象被释放。 即使保留计数为 0,该对象似乎仍保留在内存中。我在夏天搬到了 ARC,并进行了自动转换。我只是想知道我是否有一个简单的基本缺陷导致对象被保留并且永远不会释放/释放。

在类本身中实例化的对象是否设置为零? 例如我需要将其设置为 nil:

_mediaPlayerHelper = [[DOMediaPlayerHelper alloc] init:self];

在 ARC 之前我会这样做,但现在我没有在从视图堆栈中删除视图控制器时调用的函数(并且可以被删除,但这只是在返回一个级别时,而不是在转到详细视图控制器)。

【问题讨论】:

  • 可能需要弱一点,是的。我认为您在那里遇到了保留周期问题。使用 Instruments 和 Allocations 工具来发现这些
  • 您是否在DOArticleListViewController 中注册任何观察者或运行任何计时器?
  • 如果我让 NSFetchedResultsController 变弱,我会丢失 detailviewcontroller 的对象。除了该类是 tableView 的代表之外,我没有任何观察者。如果有一个函数,我可以将对象放在'nil'上,只有在查看控制器被管道时(不是例如,选择行时,viewdiddiseapear将无法正常工作) span>
  • 刚刚检查了仪器。每个新实例都活着,但我该如何检查原因。他们的引用计数为 1,但我如何检查它的来源?
  • 认为有一个更根本的问题,请参阅编辑

标签: ios objective-c uiviewcontroller uinavigationcontroller automatic-ref-counting


【解决方案1】:

我认为您可以为

创建一个属性和一个延迟实例化
DOArticleListViewController* listView

-(DOArticleListViewController*)listView{
    if (!_listView){
        _list = [[[self navigationController] storyboard] instantiateViewControllerWithIdentifier:@"DOArticleListViewController"];
    }
    return _listView;
}

这样,您可以重复使用您的 VC。

已编辑:

回应关于后退按钮的评论

// Set the left button for menu
UIImage *menuImage = [UIImage imageNamed:@"back_image"];

//create the button and assign the image
UIButton *menuButton = [UIButton buttonWithType:UIButtonTypeCustom];
[menuButton setImage:menuImage forState:UIControlStateNormal];

[menuButton addTarget:self action:@selector(backButtonEvent:) forControlEvents:UIControlEventTouchUpInside];

//create a UIBarButtonItem with the button as a custom view
UIBarButtonItem *menuBarItem = [[UIBarButtonItem alloc] initWithCustomView:menuButton];
self.navigationItem.leftBarButtonItem = menuBarItem;

然后在 backButtonEvent 方法上,您可以添加所有干净的操作,然后为当前 VC 弹出:

-(IBAction)backButtonPressed:(id)sender{
    //Clear here
    [self.navigationController popViewControllerAnimated:YES];
}

【讨论】:

  • 这是个好主意,我会考虑一些课程。但是,在其他一些视图(菜单)中,有时我有子菜单,因此确实需要特定的实例,而且它还没有帮助确定是什么导致视图不被释放。
  • 是的,你是对的。您可以为此做的另一件事是用您自己的“后退”方法覆盖后退按钮,并在为 VC 制作弹出窗口之前清除所有强引用、观察者和委托。
  • 是否有特定的内置功能,或者只是通过创建自己的按钮和操作?
  • 谢谢,我也可以使用它。但是,目前我已经在stackoverflow.com/questions/1816614/… 中实现了第二个答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多