我正在研究一个模块,将自定义注释放在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
放入我的CustomPinAnnotationView中的CustomAnnotationView
和#define UsesPinAnnotationView 1
,并且没有一个像我想的那样工作(我认为它只是使用了第一个#define预处理器来了并且丢弃了另一个#define - 最后它在所有情况下使它成为MKAnnotationView子类并且我的代码成功编译,但随后在unrecognizedSelector上崩溃(setAnimatesDrop:)
我一直在研究使用ObjC Runtime API在运行时从常用实现文件中向我的具体子类添加方法,但这似乎不是一个可行(或必要)的解决方案。
所以,这不是多重继承......它是变量继承。似乎可以在不绕过框架约束的情况下执行某些操作。有什么想法吗?
答案 0 :(得分:1)
你是对的:对于那些能够提供更好解决方案的东西来说,对运行时等进行攻击并不是一个好主意。
通过使用组合而不是继承,您可以将所有可重用逻辑隔离到每个类将包含的另一个类中:
CustomAnnotationView CustomPinAnnotationView
/ \ / \
/ has a has a \
is a V V is a
\ CustomBaseAnnotationImplementation /
\ /
\ /
V V
MKAnnotationView <----is a -- MKPinAnnotationView
或者,在惯用目标-C中执行此操作的另一种方法是在MKAnnotationView上使用一个类别来定义您的自定义逻辑/动画/ hoo-hah,其头部导入到CustomAnnotationView和CustomPinAnnotationView的实现中。这充分利用了MKPinAnnotationView只是一个奇特的MKAnnotationView这一事实,因此这两种方法都可以使用这些方法。
这有帮助吗?
答案 1 :(得分: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建议的那样,合成将是一个非常好的选择)。