Method Swizzling我的理解是运用Runtime获取类与类之间的方法,并且可以进行对换,从而达到某些目的,但是通过学习感觉和继承或者分类上使用父类的方法差不多,这种方式去搞,反而有点让接手的人不知所然,只是让外人觉得略微显得有点逼格一点。运行时可以对分类增加属性,在SDImageView中有大量使用,正常在分类中增加属性是无效的
objc_setAssociatedObject(self, &imageURLStorageKey, storage, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
学习代码创建三个类,
FOO、Bar、BarCategatory
#import <Foundation/Foundation.h>
@interface Foo : NSObject
- (void) testMethod;
- (void) baseMethod;
- (void) recursionMethod;
+ (BOOL)swizzleMethod:(SEL)origSel withMethod:(SEL)altSel;
+ (BOOL)swizzleClassMethod:(SEL)origSel withClassMethod:(SEL)altSel;
@end
//
// Foo.m
// AuditionTest
//
// Created by xie on 16/4/14.
// Copyright © 2016年 CJH. All rights reserved.
//
#import "Foo.h"
#import <objc/runtime.h>
@implementation Foo
- (void) testMethod
{
NSLog(@" >> Foo testMethod");
}
- (void) baseMethod
{
NSLog(@" >> Foo baseMethod");
}
- (void) recursionMethod
{
NSLog(@" >> Foo recursionMethod");
}
//交换方法
+ (BOOL)swizzleMethod:(SEL)origSel withMethod:(SEL)altSel
{
Method origMethod = class_getInstanceMethod(self, origSel);
if (!origSel) {
NSLog(@"original method %@ not found for class %@", NSStringFromSelector(origSel), [self class]);
return NO;
}
Method altMethod = class_getInstanceMethod(self, altSel);
if (!altMethod) {
NSLog(@"original method %@ not found for class %@", NSStringFromSelector(altSel), [self class]);
return NO;
}
class_addMethod(self,
origSel,
class_getMethodImplementation(self, origSel),
method_getTypeEncoding(origMethod));
class_addMethod(self,
altSel,
class_getMethodImplementation(self, altSel),
method_getTypeEncoding(altMethod));
method_exchangeImplementations(class_getInstanceMethod(self, origSel), class_getInstanceMethod(self, altSel));
return YES;
}
+ (BOOL)swizzleClassMethod:(SEL)origSel withClassMethod:(SEL)altSel
{
Class c = object_getClass((id)self);
return [c swizzleMethod:origSel withMethod:altSel];
}
@end
#import "Foo.h"
@interface Bar : Foo
- (void) testMethod;
@end
#import "Bar.h"
@implementation Bar
- (void) testMethod
{
NSLog(@" >> Bar testMethod");
}
@end
#import "Bar.h"
@interface Bar (BarCategory)
- (void) altTestMethod;
- (void) altBaseMethod;
- (void) altRecursionMethod;
@end
#import "Bar+BarCategory.h"
@implementation Bar (BarCategory)
- (void) altTestMethod
{
NSLog(@" >> Bar(BarCategory) altTestMethod");
}
- (void) altBaseMethod
{
NSLog(@" >> Bar(BarCategory) altBaseMethod");
}
- (void) altRecursionMethod
{
NSLog(@" >> Bar(BarCategory) recursionMethod");
[self altRecursionMethod];
}
@end
main行数测试
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "Foo.h"
#import "Bar+BarCategory.h"
#import "Bar.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
@autoreleasepool
{
Foo * foo = [[Foo alloc] init];
Bar * bar = [[Bar alloc] init];
NSLog(@"========= Method Swizzling test 1 =========");
NSLog(@" Step 1");
[foo testMethod];
[bar testMethod];
[bar altTestMethod];
NSLog(@" Step 2");
[Bar swizzleMethod:@selector(testMethod) withMethod:@selector(altTestMethod)];
[foo testMethod];
[bar testMethod];
[bar altTestMethod];
NSLog(@"========= Method Swizzling test 2 =========");
NSLog(@" Step 1");
[foo baseMethod];
[bar baseMethod];
[bar altBaseMethod];
NSLog(@" Step 2");
[Bar swizzleMethod:@selector(baseMethod) withMethod:@selector(altBaseMethod)];
[foo baseMethod];
[bar baseMethod];
[bar altBaseMethod];
NSLog(@"========= Method Swizzling test 3 =========");
[Bar swizzleMethod:@selector(recursionMethod) withMethod:@selector(altRecursionMethod)];
[bar recursionMethod];
}
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}