你好,歡迎來到IOS教程網

 Ios教程網 >> IOS訊息 >> 關於IOS >> objc_runtime使用方法的幾個簡單例子

objc_runtime使用方法的幾個簡單例子

編輯:關於IOS

1. 給NSObject類動態添加屬性
h定義部分

[cpp] 
@interface UIWebView (LoadProgress) 
 
@property (nonatomic, assign) NSInteger resourceCount; 
 
@end 

@interface UIWebView (LoadProgress)

@property (nonatomic, assign) NSInteger resourceCount;

@end

m實現部分

首先要定義一個全局的key

[cpp] 
// resourceCount object keys  
static void *s_resourceCountKey = &s_resourceCountKey; 
//static void *s_resourceCountKey = "s_resourceCountKey"; 

// resourceCount object keys
static void *s_resourceCountKey = &s_resourceCountKey;
//static void *s_resourceCountKey = "s_resourceCountKey";
初始

[cpp]
@implementation UIWebView (LoadProgress) 
@dynamic resourceCount; 

@implementation UIWebView (LoadProgress)
@dynamic resourceCount;
實現
[cpp]
#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); 

#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
基本替換方法

[cpp]
// 替換類方法  
// 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; 

// 替換類方法
// 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;
}

新方法定義

[cpp]
// 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); 

// 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中

[cpp] 
+ (void)load 

    s_UIWebView__identifierForInitialRequest_Imp = (id (*)(id, SEL, id, id, id))HLSSwizzleSelector(self, @selector(webView:identifierForInitialRequest:fromDataSource:), (IMP)swizzled_UIWebView__identifierForInitialRequest_Imp); 

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

[cpp] 
#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]; 

#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中
[cpp]
// [self implementsProtocol:@protocol(UIActionSheetDelegate)] 

// [self implementsProtocol:@protocol(UIActionSheetDelegate)][cpp] view plaincopyprint?
// 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; 

// 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;
}

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved