在超视图之后,MKMapView仍然将消息发送给委托
编辑:改变了标题。 我当时不知道,但是这是一个重复的为什么我崩溃后MKMapView被释放,如果我不再使用它?
这个问题与使用ARC + NSZombieEnabled时为什么不释放对象类似,但是我认为值得抛出,以防万一有人理解,可以向我解释发生了什么。 另一个问题可能是一个XCode错误,所以我认为这可能是类似的。
场景:
-
RootViewController
有一个显示一堆项目的tableView
- select一个单元格呈现一个模式
detailViewController
包含另一个tableView
-
detailViewController
其中一个表格单元格包含显示该项目位置的MKMapView
-
mapView.delegate = detailViewController
- closures模式
detailViewController
不久之后,应用程序崩溃b / c的MKMapView
发送mapView:viewForAnnotation:
到现在dealloc'ed detailViewController
。 这个崩溃重新在用户设备上进行临时分发构build,所以这个问题与NSZombieEnabled
无关。
我能够通过添加以下内容来解决崩溃问题:
_mapView.delegate = nil;
到包含mapView的tableViewCell
的dealloc
方法。
问题:当cell被释放时,为什么需要删除这个代表呢? 看起来像mapView
应该被ARC释放,当细胞被释放时,这是不必要的。 这是一个很好的做法,可以让代表无效,但是我不认为在这种情况下是必须的。
编辑: detailViewController
和UITableViewCells
所有子视图声明为(nonatomic, strong)
属性ala:
@property (nonatomic, strong) MKMapView * mapView;
编辑2:猜猜我需要更好地阅读文档。 @fluchtpunkt是正确的。 以下是MKMapView
文档中的相关信息:
在释放已设置委托的MKMapView对象之前,请记住将该对象的委托属性设置为nil。 一个你可以做的地方是在你处理地图视图的dealloc方法中。
MKMapView没有用ARC编译,因此delegate
的属性仍然被声明为assign
而不是weak
。
从MKMapView文档 :
@property(nonatomic, assign) id<MKMapViewDelegate> delegate
从过渡到ARC发行说明 :
如果您需要pipe理资源,而不是释放实例variables,则可以实施dealloc方法。 您不必(实际上不能)释放实例variables,但是您可能需要在系统类和其他未使用ARC编译的代码上调用[systemClassInstance setDelegate:nil] 。
对于系统类(NS *,UI *)的委托,当您释放委托对象时,必须使用设置委托的“旧”规则为nil。
所以添加一个dealloc方法到你的detailViewController
- (void)dealloc { self.mapView.delegate = nil; }
虽然这样的类的代表应该被明确地设置nil
,但是在dealloc
这样做已经太晚了。 在viewDidUnload
期间,您已经失去了对mapview的引用。 你应该做的self.mapView.delegate = nil
BEFORE的viewDidUnload
(所以可能viewWillDisappear
或viewDidDisappear
)
根据我的经验,只有MKMapView
和UIWebView
行为是这样的。