为MapKit设置单独的委托类的正确方法是什么?
我有MapView类子类化MKMapView和裸MapDelegate类符合MKMapViewDelegate协议只有一个初始化方法。
以下是我使用的MapView初始化方法的摘录:
# MapView.m ...
@implementation MapView
- (id) initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// [self setShowsUserLocation:YES];
[self setDelegate:[[MapDelegate alloc] initWithMapView:self]];
MapDelegate类唯一的方法是
# MapDelegate.m ...
- (id)initWithMapView:(MapView *)aMapView {
self = [super init];
self.mapView = aMapView;
return self;
}
[self setShowsUserLocation:YES]; 发表评论,一切正常 - 我看到了地图。如果我取消注释这一行,我的应用程序就会崩溃。
我的MapDelegate类丢失了什么?
更新1:如果我不使用单独的MapDelegate类并且只设置setDelegate:self - 一切正常。
更新2:现在我明白了, [self setDelegate:[[MapDelegate alloc] initWithMapView:self]]; 字符串的问题是我需要MapDelegate类比现在更长寿(委托属性具有弱属性)。如果我执行以下操作:
@property (strong) id delegateContainer;
....
[self setDelegateContainer:[[MapDelegate alloc] init]];
[self setDelegate:self.delegateContainer];
......它有效!有没有更好的方法来保留MapDelegate生命周期和MKMapView之一?
谢谢!
答案 0 :(得分:2)
在等待可能出现在这里的任何答案并再次确保原始问题行为两次之后,我会根据问题的第二次更新发布我自己的答案:
[self setDelegate:[[MapDelegate alloc] initWithMapView:self]]的问题; string是MapDelegate类应该能够在问题的 initWithFrame 方法范围之外保持活动,因为 delegate 属性具有弱属性。可能的解决方案是创建一个实例变量,作为委托类的容器,例如:
@property (strong) id delegateClass;
....
[self setDelegateClass:[[MapDelegate alloc] init]];
[self setDelegate:self.delegateClass];
这解决了原始问题。
稍后更新
虽然可以在单独的类中设置MKMapView的委托,但我现在意识到不应该使用这样的模型:
目前我总是喜欢使用我的控制器(即MVC中的控制器层)作为我所有View层类的代表(地图视图,滚动视图,文本字段):控制器级别是所有代表的所在不同的视图可以满足 - 所有这些视图都位于控制器层中,它们可以轻松地相互交互,并与控制器的一般逻辑共享逻辑。
另一方面,如果您在一个单独的类中设置委托,则需要采取其他步骤将单独的委托与某个控制器连接起来,这样它就可以与逻辑的其余部分进行交互 - 这项工作总是如此导致我添加了额外的杂乱代码。
很快:不要为委托使用单独的类(至少是Apple提供的视图类委托),使用一些常见的地方,如控制器(fx用于UIScrollView,MKMapView,UITableView等视图或NSURLConnection等模型)。强>
答案 1 :(得分:0)
我认为viewDidLoad
是设置地图视图的更好地方。这只是一个猜测,但也许崩溃是由于视图尚未加载。
当然不推荐继承MKMapView
。您通常会将地图作为子视图,并将主视图设置为委托。来自文档:
虽然您不应该对MKMapView类本身进行子类化,但您可以通过提供委托对象来获取有关地图视图行为的信息。
最后,如果你真的想要一个单独的委托类,你不需要设置它的mapView
,因为所有委托方法都将地图作为参数传递。