我的情况比我在发帖之前看到的要复杂一些,我不太擅长内存管理。
我有一个自定义的UITableViewCell
(我们将在这里称为MyCell
),当点击它时,我将其指针传递给UITableViewController
(这里是MyController
)。我传递指针,因为我想调用这个单元格的方法,引用只在Objective-C中通过复制,所以它不会在正确的单元格上调用方法。我做了这个:
MyController.h
@interface MyController : UITableViewController {
MyCell * __autoreleasing *_cell;
}
-(instancetype)initWithCell:(MyCell * __autoreleasing *)cell;
@end
MyController.m
- (instancetype)initWithCell:(MyCell **)cell {
if (self = [super init]) {
_cell = cell;
// Checkpoint 1
}
}
然后我想在后面的代码中使用这个变量,例如定义节的数量:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Checkpoint 2
return (*_cell).contents.count; // contents being an NSArray property of the custom cell
}
问题:在"检查点"标记在这里,我有一个NSLog(@"%ld", (unsigned long)(*_cell).contents.count);
,但它显示2(正确的数字)在第一个检查点,,但在第二个检查点0,所以当我点击单元格时,会显示一个空的表格视图。
我过去通过将其存储在nonatomic, strong
属性中通过复制传递单元格,一切都工作得很好,但是通过将调用从self.cell
更改为_cell
,因为指针引用,视图现在是空的,正如我所说。这可能是一个内存管理问题,但我不知道如何解决它(相当新的Objective-C,第一个应用程序)。
注意:我试图通过__strong
更改__autoreleasing
,但这会导致每次访问_cell
的属性时崩溃。我也尝试过使用nonatomic, assign
属性来存储它,而不是使用ivar,但它没有解决我的问题。
谢谢!
编辑:忘了说我通过使用
来调用视图控制器[self.navigationController pushViewController:[[MyController alloc] initWithCell:(MyCell **)&cell] animated:YES];
在我之前的视图控制器中,在tableView:didSelectRowAtIndexPath:
方法中。
几点说明:
-
* __autoreleasing *
模式服务于一个非常特殊的目的,即一个被调用的方法创建了一个对象,并且需要更新调用方的指针来引用这个新对象。例如,考虑正则表达式文档中的一个示例:NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\b(a|b)(c|d)\b" options:NSRegularExpressionCaseInsensitive error:&error];
所以,
error
是一个NSError
指针,调用者是提供那个指针的地址,这样regularExpressionWithPattern
实例化aNSError
对象,它可以更新调用者的引用以指向它。唯一需要使用这种"指针指向指针"模式的时候当被调用的例程正在实例化对象并想要实例化时更新调用例程的指针。我们通常只需要当您希望返回指向多个指针的指针时,请使用该模式对象(例如,在
regularExpressionWithPattern
的情况下,它将返回一个NSRegularExpression *
指针,但也可以我也想更新NSError *
指针)。 你说 :
我传递指针,因为我想调用这个单元格的方法,引用只在Objective-C中通过复制,所以它不会调用正确单元格的方法。
那个逻辑不太正确。
MyCell *
是指向该对象的指针原物,不是复制品。你可以不用诉诸于"指针指向指针"模式。对你来说,如果你只会使用MyCell *
,而不是MyCell * *
。你根本不应该传递一个单元格引用给这个视图控制器…一个视图控制器不应该触及到另一个视图控制器的视图层次;
表视图具有与单元格重用相关的各种优化…我们不应该在单元格自身的表视图数据源和委托方法中使用超出交互范围的单元格;和
不应该使用单元格("视图"对象)来存储"模型"数据(当前存储在
contents
属性中)。不要把"模型"(数据)和"视图"(UI)混为一谈。
所以,我建议一个简单的指针(不是指针指向指针的指针)指向模型对象:
@interface MyController : UITableViewController
@property (nonatomic, strong) NSArray <ModelObject *> *contents; // or whatever you previously stored in cell `contents`
@end
然后:
MyController *controller = [[MyController alloc] init]; // usually we'd instantiate it using a storyboard reference, but I'm gather you're building your view hierarchy manually
controller.contents = self.contents[indexPath.row]; // note, not `cell.contents`, but rather refer to this current view controller’s model, not the cell (the “view”)
[self.navigationController pushViewController:controller animated:YES];
关于在视图控制器之间传递数据,请参见在视图控制器之间传递数据。但是,作为一般规则,一个视图控制器不应该访问另一个视图对象。