0

我正在开发一个将自定义注释放在 MKMapView 上的模块。我的大部分逻辑目前都在一个继承自 MKAnnotationView 的类中。我已经手动将所有相同的代码复制并粘贴到另一个继承自 MKPinAnnotationView 的类中,因此客户端地图代表可以使用任一自定义子类,具体取决于他们是否需要默认的图钉图像/动​​画。

为了使这段代码更容易维护/调试,我很想干掉这段代码,让我的两个自定义类都继承自同一个类。但是,我还没有找到一个合适的干净的方法来实现这个继承图:

CustomAnnotationView              CustomPinAnnotationView
            \                       /
             \                     /
              V                   V
        CustomBaseAnnotationImplementation
            /                      \
           /                        \
          V                          V
 MKAnnotationView              MKPinAnnotationView

我试着做这样的事情:

#if UsesPinAnnotationView
#define CustomStandInSuperClass MKPinAnnotationView
#else
#define CustomStandInSuperClass MKAnnotationView
#endif

@interface CustomBaseAnnotationViewImplementation : CustomStandInSuperClass

然后把#define UsesPinAnnotationView 0我的CustomAnnotationView#define UsesPinAnnotationView 1我的CustomPinAnnotationView放进去,没有一个像我想象的那样工作(我认为它只是使用了预处理器到达的第一个#define并丢弃了另一个#define——最后它使它成为MKAnnotationView的子类在所有情况下,我的代码都成功编译,但随后在无法识别的选择器上崩溃(setAnimatesDrop :)

我一直在研究使用 ObjC Runtime API 在运行时从公共实现文件向我的具体子类添加方法,但这似乎不是一个可行(或必要)的解决方案。

所以,这不是多重继承……它是变量继承。似乎在不规避框架约束的情况下应该可以做到的事情。有任何想法吗?

4

2 回答 2

1

你是对的:对运行时等进行黑客攻击对于如此适合更好解决方案的东西来说并不是一个好主意。

通过使用组合而不是继承,您可以将所有可重用逻辑隔离到每个类将包含的另一个类中:

CustomAnnotationView              CustomPinAnnotationView
     /      \                        /       \
    /       has a                 has a       \
 is a          V                   V          is a
   \    CustomBaseAnnotationImplementation     /
    \                                         /
     \                                       /
      V                                     V
 MKAnnotationView <----is a -- MKPinAnnotationView

或者,在惯用的 Objective-C 中执行此操作的另一种方法是在 MKAnnotationView 上使用一个类别,该类别定义您的自定义逻辑/动画/hoo-hah,您将其标题导入到 CustomAnnotationView 和 CustomPinAnnotationView 的实现中。这利用了 MKPinAnnotationView 只是一个花哨的 MKAnnotationView 的事实,因此这些方法将在两个类上都可用。

这有帮助吗?

于 2012-10-26T04:31:26.837 回答
0

您正在组合两种不同的预处理器指令方法。

这些中的任何一个都应该适合您:

// Method 1:

#define UsesPinAnnotationView
// or #undef UsesPinAnnotationView

#ifdef UsesPinAnnotationView
#define CustomStandInSuperClass MKPinAnnotationView
#else
#define CustomStandInSuperClass MKAnnotationView
#endif

或者

// Method 2:

#define UsesPinAnnotationView (1) // or 0 instead of 1

#if(UsesPinAnnotationView)
#define CustomStandInSuperClass MKPinAnnotationView
#else
#define CustomStandInSuperClass MKAnnotationView
#endif

但是请注意,虽然这可以解决您遇到的问题,但有更好的方法可以做到这一点(正如@AndrewPouliot 建议的那样,组合将是一个非常好的选择)。

于 2012-10-26T04:16:49.057 回答