【问题标题】:The right way of setting up MapKit's delegate in a separate class在单独的类中设置 MapKit 委托的正确方法
【发布时间】:2012-09-07 02:46:02
【问题描述】:

为 MapKit 设置单独的委托类的正确方法是什么?

我有 MapView 类子类化 MKMapView 和符合 MKMapViewDelegate 协议的裸 MapDelegate 类只有一个初始化方法。

这是我使用的 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 类的寿命比现在长(委托属性具有 weak 属性)。如果我执行以下操作:

@property (strong) id delegateContainer;
....
[self setDelegateContainer:[[MapDelegate alloc] init]];
[self setDelegate:self.delegateContainer];

...有效!有没有更好的方法来保留 MapDelegate 生命周期以及 MKMapView 的生命周期?

谢谢!

【问题讨论】:

    标签: objective-c ios mkmapview mapkit


    【解决方案1】:

    在等待足够长的时间等待可能出现在这里的任何答案并再次确保原始问题行为两次之后,我将根据问题的第二次更新发布我自己的答案:

    [self setDelegate:[[MapDelegate alloc] initWithMapView:self]]的问题; string 是 MapDelegate 类应该能够在问题的 initWithFrame 方法范围之外保持活动状态,因为 delegate 属性具有 weak 属性。可能的解决方案是创建一个实例变量作为委托类的容器,例如:

    @property (strong) id delegateClass;
    ....
    [self setDelegateClass:[[MapDelegate alloc] init]];
    [self setDelegate:self.delegateClass];
    

    这解决了原来的问题。

    稍后更新

    虽然可以在单独的类中设置 MKMapView 的委托,但我现在意识到不应该使用这样的模型:

    目前我总是更喜欢使用我的控制器(即 MVC 中的控制器层)作为我所有视图层类(地图视图、滚动视图、文本字段)的代表:控制器层是所有代表的地方不同的视图可以相遇 - 都位于控制器层,它们可以轻松地相互交互并与控制器的一般逻辑共享它们的逻辑。

    另一方面,如果您在单独的类中设置您的委托,您将需要采取额外的步骤来将您的单独委托与某个控制器连接,以便它可以与您的逻辑的其余部分进行交互 - 这项工作一直导致我添加了额外且混乱的代码。

    简而言之:不要为委托使用单独的类(至少 Apple 提供的视图类委托),使用一些常见的地方,如控制器(用于 UIScrollView、MKMapView、UITableView 等视图或 NSURLConnection 等模型的 fx)。强>

    【讨论】:

      【解决方案2】:

      我认为viewDidLoad 是设置地图视图的更好位置。这只是一个猜测,但可能崩溃是由于尚未加载视图。

      当然,完全不推荐子类化MKMapView。您通常会将您的地图作为子视图,并将主视图设置为委托。来自文档:

      虽然您不应该继承 MKMapView 类本身,但您可以通过提供委托对象来获取有关地图视图行为的信息。

      最后,如果你真的想要一个单独的委托类,你不需要设置它的mapView,因为所有的委托方法都将映射作为参数传递。

      【讨论】:

      • 感谢您的回答。我放弃了子类化,现在只是 MKMapView。我从 viewDidLoad 初始化它。我删除了设置 mapView - 你是对的,谢谢。还是一样的行为!如果我使用 setDelegate:self 一切正常。
      猜你喜欢
      • 2018-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多