您的位置:首页 > 其它

objc_runtime使用方法的几个简单例子

2013-04-18 09:49 501 查看


1. 给NSObject类动态添加属性

h定义部分

@interface UIWebView (LoadProgress)

@property (nonatomic, assign) NSInteger resourceCount;

@end


m实现部分

首先要定义一个全局的key
// resourceCount object keys
static void *s_resourceCountKey = &s_resourceCountKey;
//static void *s_resourceCountKey = "s_resourceCountKey";


初始

@implementation UIWebView (LoadProgress)
@dynamic resourceCount;


实现
#pragma mark Accessors and mutators

- (NSInteger)resourceCount
{
NSNumber *resourceCountNumber = objc_getAssociatedObject(self, s_resourceCountKey);
if (! resourceCountNumber)
{
return 0;
}
else
{
return [resourceCountNumber integerValue];
}
}

- (void)setResourceCount:(NSInteger)rCount
{
objc_setAssociatedObject(self, s_resourceCountKey, [NSNumber numberWithInteger:rCount], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}


这样就可以直接使用了

webView.resourceCount = 10;


2. 给NSObject类动态添加代理protocol

同属性
动态创建代理暂时先不写了


3. 替换或变更NSObject类方法Method

基本替换方法

// 替换类方法
// frome: CoconutKit
IMP HLSSwizzleClassSelector(Class clazz, SEL selector, IMP newImplementation)
{
// Get the original implementation we are replacing
Class metaClass = objc_getMetaClass(class_getName(clazz));
Method method = class_getClassMethod(metaClass, selector);
IMP origImp = method_getImplementation(method);
if (! origImp) {
return NULL;
}

class_replaceMethod(metaClass, selector, newImplementation, method_getTypeEncoding(method));
return origImp;
}

// 替换实例方法
IMP HLSSwizzleSelector(Class clazz, SEL selector, IMP newImplementation)
{
// Get the original implementation we are replacing
Method method = class_getInstanceMethod(clazz, selector);
IMP origImp = method_getImplementation(method);
if (! origImp) {
return NULL;
}

class_replaceMethod(clazz, selector, newImplementation, method_getTypeEncoding(method));
return origImp;
}


新方法定义

// Original implementation of the methods we swizzle
static id (*s_UIWebView__identifierForInitialRequest_Imp)(id, SEL, id, id, id) = NULL;

// Swizzled method implementations
static id swizzled_UIWebView__identifierForInitialRequest_Imp(UIWebView *self, SEL _cmd, id webView, id initialRequest, id dataSource);


方法初始化需要写在类方法+ (void)load中

+ (void)load
{
s_UIWebView__identifierForInitialRequest_Imp = (id (*)(id, SEL, id, id, id))HLSSwizzleSelector(self, @selector(webView:identifierForInitialRequest:fromDataSource:), (IMP)swizzled_UIWebView__identifierForInitialRequest_Imp);
}


实现部分

#pragma mark Swizzled method implementations

static id swizzled_UIWebView__identifierForInitialRequest_Imp(UIWebView *self, SEL _cmd, id webView, id initialRequest, id dataSource)
{
// 调用原方法
(*s_UIWebView__identifierForInitialRequest_Imp)(self, _cmd, webView, initialRequest, dataSource);

[self setResourceCount:self.resourceCount+1];

return [NSNumber numberWithInteger:self.resourceCount];
}



4. 代理方法检索

可直接定义到NSObject的Category中
// [self implementsProtocol:@protocol(UIActionSheetDelegate)]
// frome: CoconutKit
- (BOOL)implementsProtocol:(Protocol *)protocol
{
// Only interested in optional methods. Required methods are checked at compilation time
unsigned int numberOfMethods = 0;
struct objc_method_description *methodDescriptions = protocol_copyMethodDescriptionList(protocol, NO /* optional only */, YES, &numberOfMethods);
for (unsigned int i = 0; i < numberOfMethods; ++i) {
struct objc_method_description methodDescription = methodDescriptions[i];
SEL selector = methodDescription.name;
if (! class_getInstanceMethod([self class], selector)) {
NSString *selectorString = [NSString stringWithCString:sel_getName(selector) encoding:NSUTF8StringEncoding];
NSString *protocolName = [NSString stringWithCString:protocol_getName(protocol) encoding:NSUTF8StringEncoding];
HLSLoggerInfo(@"Class %@ does not implement method %@ of protocol %@", [self className], selectorString, protocolName);
selectorString = nil;               // Just to remove unused variable warnings
protocolName = nil;
return NO;
}
}

return YES;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: