Several simple examples of objc_runtime usage

Source: Internet
Author: User

1. dynamically add attributes to the NSObject class
H Definition

[Cpp]
@ Interface UIWebView (LoadProgress)
 
@ Property (nonatomic, assign) NSInteger resourceCount;
 
@ End

@ Interface UIWebView (LoadProgress)

@ Property (nonatomic, assign) NSInteger resourceCount;

@ End

M implementation

First, define a global 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 ";
Initial

[Cpp]
@ Implementation UIWebView (LoadProgress)
@ Dynamic resourceCount;

@ Implementation UIWebView (LoadProgress)
@ Dynamic resourceCount;
Implementation
[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 );
}

In this way, you can use it directly.

WebView. resourceCount = 10;

 

 

2. dynamically Add a proxy protocol to the NSObject class
Same attribute

No more proxies are created.

 


3. replace or change the NSObject Class Method
Basic replacement method


[Cpp]
// Replacement Class 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;
}
 
// Instance replacement method
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;
}

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

// Instance replacement method
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;
}


New method definition


[Cpp]
// Original implementation of the methods we swizzle
Static id (* s_UIWebView _ identifierForInitialRequest_Imp) (id, SEL, 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) = NULL;

// Swizzled method implementations
Static id swizzled_UIWebView _ identifierForInitialRequest_Imp (UIWebView * self, SEL _ cmd, id webView, id initialRequest, id dataSource );
Method initialization needs to be written in class method + (void) load

[Cpp]
+ (Void) load
{
S_UIWebView _ identifierForInitialRequest_Imp = (id (*) (id, SEL, id) HLSSwizzleSelector (self, @ selector (webView: identifierForInitialRequest: fromDataSource :), (IMP) swizzled_UIWebView _ identifierForInitialRequest_Imp );
}

+ (Void) load
{
S_UIWebView _ identifierForInitialRequest_Imp = (id (*) (id, SEL, id) HLSSwizzleSelector (self, @ selector (webView: identifierForInitialRequest: fromDataSource :), (IMP) swizzled_UIWebView _ identifierForInitialRequest_Imp );
}
Implementation

[Cpp]
# Pragma mark Swizzled method implementations
 
Static id swizzled_UIWebView _ identifierForInitialRequest_Imp (UIWebView * self, SEL _ cmd, id webView, id initialRequest, id dataSource)
{
// Call the original method
(* 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)
{
// Call the original method
(* S_UIWebView _ identifierForInitialRequest_Imp) (self, _ cmd, webView, initialRequest, dataSource );

[Self setResourceCount: self. resourceCount + 1];

Return [NSNumber numberWithInteger: self. resourceCount];
}


4. Proxy method Retrieval
Can be directly defined in the 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;
}

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.