Doz*_*Doz 97 objective-c clang
我想知道如何压制警告:
类别正在实施一种方法,该方法也将由其主要类实现.
我有一个特定的代码类别:
+ (UIFont *)systemFontOfSize:(CGFloat)fontSize {
return [self aCustomFontOfSize:fontSize];
}
Run Code Online (Sandbox Code Playgroud)
Ben*_*ron 341
虽然所有人都说是正确的,但它实际上并没有回答你如何压制警告的问题.
如果由于某种原因你必须有这个代码(在我的情况下我在我的项目中有HockeyKit并且它们覆盖了UIImage类别中的方法[编辑:这不再是这种情况])并且你需要让你的项目编译,您可以使用#pragma语句来阻止警告,如下所示:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
// do your override
#pragma clang diagnostic pop
Run Code Online (Sandbox Code Playgroud)
我在这里找到了这些信息:http://www.cocoabuilder.com/archive/xcode/313767-disable-warning-for-override-in-category.html
bne*_*ely 63
类别允许您向现有类添加新方法.如果要重新实现类中已存在的方法,通常需要创建子类而不是类.
Apple文档:自定义现有类
如果在类别中声明的方法的名称与原始类中的方法相同,或者在同一个类(或甚至是超类)上的另一个类别中的方法相同,则关于在哪个方法实现中使用哪个方法实现的行为是未定义的.运行.
在同一个类中具有完全相同签名的两个方法将导致不可预测的行为,因为每个调用者都无法指定他们想要的实现.
因此,您应该使用类别并为类提供新的和唯一的方法名称,或者如果要更改类中现有方法的行为,则提供子类.
San*_*uja 20
一个更好的选择(参见bneely的回答,为什么这个警告可以帮助你免受灾难)是使用方法调配.通过使用方法调配,您可以从类别中替换现有方法,而不必具有"获胜"的不确定性,同时保留调用旧方法的能力.秘诀是为覆盖提供不同的方法名称,然后使用运行时函数交换它们.
#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);
}
Run Code Online (Sandbox Code Playgroud)
然后定义您的自定义实现:
+ (UIFont *)mySystemFontOfSize:(CGFloat)fontSize {
...
}
Run Code Online (Sandbox Code Playgroud)
用你的覆盖默认实现:
MethodSwizzle([UIFont class], @selector(systemFontOfSize:), @selector(mySystemFontOfSize:));
Run Code Online (Sandbox Code Playgroud)
Vit*_*zuk 10
在您的代码中尝试此操作:
+(void)load{
EXCHANGE_METHOD(Method1, Method1Impl);
}
Run Code Online (Sandbox Code Playgroud)
UPDATE2:添加此宏
#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
Run Code Online (Sandbox Code Playgroud)
您可以使用方法调配来抑制此编译器警告.以下是当我们使用UITextBorderStyleNone的自定义背景时,我如何实现方法调整以在UITextField中绘制边距:
#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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
38504 次 |
| 最近记录: |