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