Reputation: 67
I have a class that handles paginated data for me. This class has the following properties:
@property (nonatomic, weak) UITableView *tableView;
@property (nonatomic, weak) id <DataSourceProtocol> dataSource;
I have a view controller that tells the pagination controller to load more data when needed. The pagination controller then tells its dataSource it needs new data, the dataSource downloads this data and lets the pagination controller know. The pagination controller saves this data and reloads its table view.
The problem comes when the view controller is deallocated during this process. For example, data is currently being retrieved by the pagination data source when the view controller is dismissed. Once the new data arrives and is passed to the pagination controller, the pagination controller tells its tableView to reloadData. Crash. Somehow at this point the tableView's delegate and dataSource (the view controller) are non-nil, despite being deallocated. The reference is now rubbish and the crash occurs.
I have seen some other questions and answers like this: Weak property not zeroing using ARC But most deal with method calls that pass the weak reference as an argument, which mine does not.
Here is brief outline of the code (simplified and stripped down):
// In the view controller (also the pagination dataSource):
// Called by the pagination controller to get more data it needs
- (void)PCNeedsData:(PC *)pc
{
[_obj getData:^(NSArray *data) {
// By now the view controller is deallocated
[pc addData:data];
}];
}
// In the pagination controller
- (void)addData:(NSArray *)data
{
[_data addObjectsFromArray:data];
[_tableView reloadData]; // Crash because _tableView.delegate / dataSource are deallocated but non-nil
}
Obviously I can fix this issue by explicitly nilling out the tableView's delegate and dataSource in the view controller's dealloc. But I am mostly just curious why this step is needed. Do the blocks somehow cause the weak references to be retained (even though it is never referenced in the block / that makes no sense)?
Any help would be greatly appreciated.
Upvotes: 1
Views: 686
Reputation: 2762
Many of Apple's classes still use assign
, rather than weak
. You can check this yourself in the docs or the header file (command-click the delegate or dataSource property in Xcode). assign
is the same as unsafe_unretained
, which means if the object it's referencing is deallocated, it is not automatically set to nil.
Upvotes: 1