我意识到这个问题存在一些主观性,但考虑到Apple开发对于命名约定非常自以为是,我想以其他人理解我的编码所做的方式来做这件事。我试图以最通用的方式提出问题,但我会在评论中添加一些我的具体细节,以防它影响您的答案。
假设我支持iOS 6和iOS 7.现有类中有一种新方法仅存在于iOS 7 SDK中。假设以对我的应用程序“足够好”的方式实现功能是相当简单的。但是,当然,我宁愿使用SDK版本,因为它可能会得到更好的支持,更高效,更好地处理边缘情况。
如this Q&A中所述,处理这种情况很简单。
if ([myInstance respondsToSelector:@selector(newSelector)]) {
//Use the SDK method
} else {
//Use my "good enough" implementation.
}
但我不想在一大堆条件调用中丢弃我的代码。似乎封装这种动态方法选择会更好。 (特别是在我的情况下,该方法尚未实际发货且名称/签名可能会发生变化。)
我的直觉是添加一个实现我的功能的类类别以及实现这种动态选择方法的包装器方法。
这是正确的做法吗?如果是这样,我应该使用哪些命名约定? (我显然不能将我的方法命名为与iOS7方法相同,否则会出现命名冲突。)
我的直觉反应是调用我的包装器方法safeNewSelector和我的实现一个名为lwNewSelector的私有方法(其中lw是我的标准类前缀)。但我宁愿使用一些被认为是标准命名约定的东西。
答案 0 :(得分:3)
我的直觉是添加一个实现我的功能的类类别以及实现这种动态选择方法的包装器方法。
听起来不错。 naming convention for category methods是小写前缀,加上下划线。因此,如果要隐藏名为doSomething:withAwesome:
的方法,则应将类别方法命名为ogr_doSomething:withAwesome:
(假设您使用OGR
作为公共前缀)。
你真的必须为类别方法添加前缀。如果两个类实现相同的方法,则将运行未定义的行为。您不会收到编译时或运行时错误。你只会得到未定义的行为。 (而Apple可以并且确实在类别中实现“核心”功能,并且您无法轻易检测到他们已经这样做了。)
答案 1 :(得分:2)
转到某个类别并选择一个非常独特的名称,例如以某个公司/项目特定前缀作为前缀。假设iOS 7中的方法将被称为funky
,您选择前缀foo
。然后你会做:
@implementation SomeClass(FooCategory)
- (void)foo_funky
{
if ([self respondsToSelector:@selector(funky)]) {
[self funky];
} else {
// Implementation of workaround.
}
}
@end
现在,每当你打电话foo_funky
时,都需要做出决定。效率很低。我刚刚想到,Objective-C可以通过弄乱运行时来提高效率,类似于方法调整(代码未经测试):
@implementation SomeClass(FooCategory)
- (void)foo_funky
{
// Empty implementation, it will be replaced.
}
- (void)foo_myFunkyImplementation
{
// Workaround implementation in case the iOS 7 version is missing.
}
+ (void)load
{
Method realMethod, dummyMethod;
realMethod = class_getInstanceMethod(self, @selector(funky));
if (!realMethod) {
// iOS7 method not available, use my version.
realMethod = class_getInstanceMethod(self, @selector(foo_myFunkyImplementation));
}
// Get the method that should be replaced.
dummyMethod = class_getInstanceMethod(self, @selector(foo_funky));
// Overwrite the dummy implementation with the real implementation.
method_setImplementation(dummyMethod, method_getImplementation(realMethod));
}
@end
这样每次调用foo_funky
时,都会调用正确的方法,而不会产生响应选择器和后续调用其他方法的开销。
您也可以使用运行时类修改在官方名称不可用时添加您的实现,但我不建议这样做。如果您可以通过方法名称判断它可能不是您期望的版本,那就更好了。
答案 2 :(得分:0)
这确实是一个公平的问题,我认为很多Objective-C debs都遇到了这种情况。
我自己在几个地方使用了类别建议的方法。至于命名,在大多数情况下,我在我的类别方法中添加了一些额外的功能,所以我的方法名称大部分时间采用另一个参数 - 在大多数情况下,简单的animated:(BOOL)animated
添加到“官方”的末尾方法名称。
是的,存在与未来SDK版本发生冲突的风险,但我不会太担心它,Xcode的重构效果相当好,并且当类别方法发生冲突时,您会收到链接器警告。
编辑: 正如Rob指出的那样,使用该命名约定可能是一个好主意。