禁止警告“类别正在实施一个方法,也将由其主要类实施”

我想知道如何抑制这个警告:

类正在实现一个方法,也将由其主要类实现。

我有这个特定的代码类别:

+ (UIFont *)systemFontOfSize:(CGFloat)fontSize { return [self aCustomFontOfSize:fontSize]; } 

一个类别允许你添加新的方法到现有的类。 如果你想重新实现类中已经存在的方法,你通常创build一个子类而不是一个类。

苹果文档: 定制现有的类

如果在类别中声明的方法的名称与原始类中的方法相同,或者在同一个类(甚至是超类)上的另一个类中的方法相同,则行为是不确定的运行。

在同一个类中具有完全相同签名的两个方法将导致不可预知的行为,因为每个调用者不能指定他们想要的实现。

因此,如果要更改类中现有方法的行为,则应该使用一个类别,并提供新类别的唯一方法名称或子类别。

虽然所有的说法都是正确的,但实际上并没有回答你如何抑制警告的问题。

如果因为某种原因必须拥有这段代码(在我的例子中,我的项目中有HockeyKit,并且它们覆盖了UIImage类别中的一个方法[编辑:这不再是这种情况]),你需要让你的项目编译,你可以使用#pragma语句来阻止这样的警告:

 #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation" // do your override #pragma clang diagnostic pop 

我在这里find了这些信息: http : //www.cocoabuilder.com/archive/xcode/313767-disable-warning-for-override-in-category.html

一个更好的select(请参阅bneely的答案为什么这个警告是从灾难中拯救你)是使用方法swizzling。 通过使用方法swizzling,您可以从一个类别中replace现有的方法,而不需要“赢”谁的不确定性,同时保留调用旧方法的能力。 秘诀是给重写一个不同的方法名称,然后使用运行时函数交换它们。

 #import <objc/runtime.h> #import <objc/message.h> void MethodSwizzle(Class c, SEL orig, SEL new) { Method origMethod = class_getInstanceMethod(c, orig); Method newMethod = class_getInstanceMethod(c, new); if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod)); else method_exchangeImplementations(origMethod, newMethod); } 

然后定义您的自定义实现:

 + (UIFont *)mySystemFontOfSize:(CGFloat)fontSize { ... } 

用你的重写默认实现:

 MethodSwizzle([UIFont class], @selector(systemFontOfSize:), @selector(mySystemFontOfSize:)); 

在你的代码中试试这个:

 +(void)load{ EXCHANGE_METHOD(Method1, Method1Impl); } 

UPDATE2:添加这个macros

 #import <Foundation/Foundation.h> #define EXCHANGE_METHOD(a,b) [[self class]exchangeMethod:@selector(a) withNewMethod:@selector(b)] @interface NSObject (MethodExchange) +(void)exchangeMethod:(SEL)origSel withNewMethod:(SEL)newSel; @end #import <objc/runtime.h> @implementation NSObject (MethodExchange) +(void)exchangeMethod:(SEL)origSel withNewMethod:(SEL)newSel{ Class class = [self class]; Method origMethod = class_getInstanceMethod(class, origSel); if (!origMethod){ origMethod = class_getClassMethod(class, origSel); } if (!origMethod) @throw [NSException exceptionWithName:@"Original method not found" reason:nil userInfo:nil]; Method newMethod = class_getInstanceMethod(class, newSel); if (!newMethod){ newMethod = class_getClassMethod(class, newSel); } if (!newMethod) @throw [NSException exceptionWithName:@"New method not found" reason:nil userInfo:nil]; if (origMethod==newMethod) @throw [NSException exceptionWithName:@"Methods are the same" reason:nil userInfo:nil]; method_exchangeImplementations(origMethod, newMethod); } @end 

您可以使用方法swizzling来抑制此编译器警告。 下面是我在UITextField中使用UITextBorderStyleNone使用自定义背景时如何实现绘制边界的方法调整:

 #import <UIKit/UIKit.h> @interface UITextField (UITextFieldCatagory) +(void)load; - (CGRect)textRectForBoundsCustom:(CGRect)bounds; - (CGRect)editingRectForBoundsCustom:(CGRect)bounds; @end #import "UITextField+UITextFieldCatagory.h" #import <objc/objc-runtime.h> @implementation UITextField (UITextFieldCatagory) +(void)load { Method textRectForBounds = class_getInstanceMethod(self, @selector(textRectForBounds:)); Method textRectForBoundsCustom = class_getInstanceMethod(self, @selector(textRectForBoundsCustom:)); Method editingRectForBounds = class_getInstanceMethod(self, @selector(editingRectForBounds:)); Method editingRectForBoundsCustom = class_getInstanceMethod(self, @selector(editingRectForBoundsCustom:)); method_exchangeImplementations(textRectForBounds, textRectForBoundsCustom); method_exchangeImplementations(editingRectForBounds, editingRectForBoundsCustom); } - (CGRect)textRectForBoundsCustom:(CGRect)bounds { CGRect inset = CGRectMake(bounds.origin.x + 10, bounds.origin.y, bounds.size.width - 10, bounds.size.height); return inset; } - (CGRect)editingRectForBoundsCustom:(CGRect)bounds { CGRect inset = CGRectMake(bounds.origin.x + 10, bounds.origin.y, bounds.size.width - 10, bounds.size.height); return inset; } @end 

类别是一件好事,但可能会被滥用。 在编写类别时,应将其作为原则而不是重新实现退出方法。 这样做可能会导致奇怪的副作用,因为您现在正在重写另一个类取决于其中的代码。 你可以打破一个已知的类,最终把你的debugging器从头开始。 这只是糟糕的编程。

如果你需要待办事项,你应该inheritance它。

那么这个build议呢,这是一个很大的“不”的NO。

在运行时将其打开是一个完整的NO-NO-NO。

你想要一个香蕉看起来像一个橙色,但只在运行时? 如果你想要一个橙色,然后写一个橙色。

不要让香蕉看起来像橘子一样。 更糟糕的是,不要把你的香蕉变成一个秘密特工,他将悄悄地破坏世界各地的香蕉,支持橘子。

哎呀!

当我在类别中实现委托方法而不是主类(即使没有主类实现)时,我遇到了这个问题。 我的解决scheme是从主类头文件移动到类别头文件这工作正常

超车属性适用于类别扩展(匿名类别),但不适用于常规类别。

根据Apple Docs使用类扩展(匿名类别),您可以创build一个公共类的私有接口,使得私有接口可以覆盖公开的属性。 即您可以将属性从只读更改为readwrite。

一个用例就是当你编写限制对公共属性的访问的库时,而同一个属性需要库中的完全读写访问。

Apple Docs链接: https : //developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html

search“ 使用类别扩展来隐藏私人信息 ”。

所以这种技术对于类扩展是有效的,但对类别不适用。