NSObject(FWSwizzle)
@interface NSObject (FWSwizzle)
框架NSObject类包装器
实现block必须返回一个block,返回的block将被当成originalSelector的新实现,所以要在内部自己处理对super的调用,以及对当前调用方法的self的class的保护判断(因为如果originalClass的originalSelector是继承自父类的,originalClass内部并没有重写这个方法,则我们这个函数最终重写的其实是父类的originalSelector,所以会产生预期之外的class的影响,例如originalClass传进来UIButton.class,则最终可能会影响到UIView.class)。block的参数里第一个为你要修改的class,也即等同于originalClass,第二个参数为你要修改的selector,也即等同于originalSelector,第三个参数是一个block,用于获取originalSelector原本的实现,由于IMP可以直接当成C函数调用,所以可利用它来实现“调用 super”的效果,但由于originalSelector的参数个数、参数类型、返回值类型,都会影响IMP的调用写法,所以这个调用只能由业务自己写
-
使用swizzle替换对象实例方法为block实现,identifier相同时仅执行一次。结合fwIsSwizzleMethod使用
Declaration
Objective-C
- (BOOL)fw_swizzleInstanceMethod:(nonnull SEL)originalSelector identifier:(nonnull NSString *)identifier withBlock: (nonnull id _Nonnull (^)( __unsafe_unretained Class _Nonnull, SEL _Nonnull, IMP _Nonnull (^_Nonnull __strong)(void)))block;
Parameters
originalSelector
原始方法
identifier
唯一标识
block
实现句柄
Return Value
是否成功
-
判断对象是否使用swizzle替换过指定identifier实例方法。结合fwSwizzleMethod使用
Note
因为实际替换的是类方法,为了防止影响该类其它对象,需先判断该对象是否替换过,仅替换过才执行自定义流程
Declaration
Objective-C
- (BOOL)fw_isSwizzleInstanceMethod:(nonnull SEL)originalSelector identifier:(nonnull NSString *)identifier;
Parameters
originalSelector
原始方法
identifier
唯一标识
Return Value
是否替换
-
安全调用方法,如果不能响应,则忽略之
Declaration
Objective-C
- (nullable id)fw_invokeMethod:(nonnull SEL)aSelector;
Parameters
aSelector
要执行的方法
Return Value
id 方法执行后返回的值。如果无返回值,则为nil
-
安全调用方法,如果不能响应,则忽略之
Declaration
Objective-C
- (nullable id)fw_invokeMethod:(nonnull SEL)aSelector withObject:(nullable id)object;
Parameters
aSelector
要执行的方法
object
传递的方法参数,非id类型可使用桥接,如int a = 1;(__bridge id)(void *)a
Return Value
id 方法执行后返回的值。如果无返回值,则为nil
-
安全调用方法,支持多个参数
Declaration
Objective-C
- (nullable id)fw_invokeMethod:(nonnull SEL)aSelector withObjects:(nonnull NSArray *)objects;
Parameters
aSelector
要执行的方法
objects
传递的参数数组
Return Value
id 方法执行后返回的值。如果无返回值,则为nil
-
对super发送消息
Declaration
Objective-C
- (nullable id)fw_invokeSuperMethod:(nonnull SEL)aSelector;
Parameters
aSelector
要执行的方法,需返回id类型
Return Value
id 方法执行后返回的值
-
对super发送消息,可传递参数
Declaration
Objective-C
- (nullable id)fw_invokeSuperMethod:(nonnull SEL)aSelector withObject:(nullable id)object;
Parameters
aSelector
要执行的方法,需返回id类型
object
传递的方法参数
Return Value
id 方法执行后返回的值
-
安全调用内部属性获取方法,如果属性不存在,则忽略之
Note
如果iOS13系统UIView调用部分valueForKey:方法闪退,且没有好的替代方案,可尝试调用此方法
Declaration
Objective-C
- (nullable id)fw_invokeGetter:(nonnull NSString *)name;
Parameters
name
内部属性名称
Return Value
属性值
-
安全调用内部属性设置方法,如果属性不存在,则忽略之
Note
如果iOS13系统UIView调用部分valueForKey:方法闪退,且没有好的替代方案,可尝试调用此方法
Declaration
Objective-C
- (nullable id)fw_invokeSetter:(nonnull NSString *)name withObject:(nullable id)object;
Parameters
name
内部属性名称
object
传递的方法参数
Return Value
方法执行后返回的值
-
临时对象,强引用,支持KVO
Note
备注:key的几种形式的声明和使用,下同- 声明:static char kAssociatedObjectKey; 使用:&kAssociatedObjectKey
- 声明:static void *kAssociatedObjectKey = &kAssociatedObjectKey; 使用:kAssociatedObjectKey
- 声明和使用直接用getter方法的selector,如@selector(xxx)、_cmd
- 声明和使用直接用c字符串,如"kAssociatedObjectKey"
Declaration
Objective-C
@property (nonatomic, strong, nullable) id fw_tempObject;
-
读取关联属性
Declaration
Objective-C
- (nullable id)fw_propertyForName:(nonnull NSString *)name;
Parameters
name
属性名称
Return Value
属性值
-
设置强关联属性,支持KVO
Declaration
Objective-C
- (void)fw_setProperty:(nullable id)object forName:(nonnull NSString *)name;
Parameters
object
属性值
name
属性名称
-
设置赋值关联属性,支持KVO,注意可能会产生野指针
Declaration
Objective-C
- (void)fw_setPropertyAssign:(nullable id)object forName:(nonnull NSString *)name;
Parameters
object
属性值
name
属性名称
-
设置拷贝关联属性,支持KVO
Declaration
Objective-C
- (void)fw_setPropertyCopy:(nullable id)object forName:(nonnull NSString *)name;
Parameters
object
属性值
name
属性名称
-
设置弱引用关联属性,支持KVO,OC不支持weak关联属性
Declaration
Objective-C
- (void)fw_setPropertyWeak:(nullable id)object forName:(nonnull NSString *)name;
Parameters
object
属性值
name
属性名称
-
给对象绑定上另一个对象以供后续取出使用,如果 object 传入 nil 则会清除该 key 之前绑定的对象
Declaration
Objective-C
- (void)fw_bindObject:(nullable id)object forKey:(nonnull NSString *)key;
Parameters
object
对象,会被 strong 强引用
key
键名
-
给对象绑定上另一个弱引用对象以供后续取出使用,如果 object 传入 nil 则会清除该 key 之前绑定的对象
Declaration
Objective-C
- (void)fw_bindObjectWeak:(nullable id)object forKey:(nonnull NSString *)key;
Parameters
object
对象,不会被 strong 强引用
key
键名
-
取出之前使用 bind 方法绑定的对象
Declaration
Objective-C
- (nullable id)fw_boundObjectForKey:(nonnull NSString *)key;
Parameters
key
键名
-
给对象绑定上一个 double 值以供后续取出使用
Declaration
Objective-C
- (void)fw_bindDouble:(double)doubleValue forKey:(nonnull NSString *)key;
Parameters
doubleValue
double值
key
键名
-
取出之前用 bindDouble:forKey: 绑定的值
Declaration
Objective-C
- (double)fw_boundDoubleForKey:(nonnull NSString *)key;
Parameters
key
键名
-
给对象绑定上一个 BOOL 值以供后续取出使用
Declaration
Objective-C
- (void)fw_bindBool:(BOOL)boolValue forKey:(nonnull NSString *)key;
Parameters
boolValue
布尔值
key
键名
-
取出之前用 bindBool:forKey: 绑定的值
Declaration
Objective-C
- (BOOL)fw_boundBoolForKey:(nonnull NSString *)key;
Parameters
key
键名
-
给对象绑定上一个 NSInteger 值以供后续取出使用
Declaration
Objective-C
- (void)fw_bindInt:(NSInteger)integerValue forKey:(nonnull NSString *)key;
Parameters
integerValue
整数值
key
键名
-
取出之前用 bindInt:forKey: 绑定的值
Declaration
Objective-C
- (NSInteger)fw_boundIntForKey:(nonnull NSString *)key;
Parameters
key
键名
-
移除之前使用 bind 方法绑定的对象
Declaration
Objective-C
- (void)fw_removeBindingForKey:(nonnull NSString *)key;
Parameters
key
键名
-
移除之前使用 bind 方法绑定的所有对象
Declaration
Objective-C
- (void)fw_removeAllBindings;
-
返回当前有绑定对象存在的所有的 key 的数组,数组中元素的顺序是随机的,如果不存在任何 key,则返回一个空数组
Declaration
Objective-C
- (nonnull NSArray<NSString *> *)fw_allBindingKeys;
-
返回是否设置了某个 key
Declaration
Objective-C
- (BOOL)fw_hasBindingKey:(nonnull NSString *)key;
Parameters
key
键名
-
交换类实例方法。复杂情况可能会冲突
Declaration
Objective-C
+ (BOOL)fw_exchangeInstanceMethod:(nonnull SEL)originalSelector swizzleMethod:(nonnull SEL)swizzleSelector;
Parameters
originalSelector
原始方法
swizzleSelector
交换方法
Return Value
是否成功
-
交换类静态方法。复杂情况可能会冲突
Declaration
Objective-C
+ (BOOL)fw_exchangeClassMethod:(nonnull SEL)originalSelector swizzleMethod:(nonnull SEL)swizzleSelector;
Parameters
originalSelector
原始方法
swizzleSelector
交换方法
Return Value
是否成功
-
交换类实例方法为block实现。复杂情况可能会冲突
Note
swizzleBlock示例:^(__unsafe_unretained UIViewController selfObject, BOOL animated){ ((void()(id, SEL, BOOL))objc_msgSend)(selfObject, swizzleSelector, animated); }
Declaration
Objective-C
+ (BOOL)fw_exchangeInstanceMethod:(nonnull SEL)originalSelector swizzleMethod:(nonnull SEL)swizzleSelector withBlock:(nonnull id)swizzleBlock;
Parameters
originalSelector
原始方法
swizzleSelector
交换方法
swizzleBlock
实现block
Return Value
是否成功
-
交换类静态方法为block实现。复杂情况可能会冲突
Note
swizzleBlock示例:^(__unsafe_unretained Class selfClass, BOOL animated){ ((void(*)(id, SEL, BOOL))objc_msgSend)(selfClass, swizzleSelector, animated); }
Declaration
Objective-C
+ (BOOL)fw_exchangeClassMethod:(nonnull SEL)originalSelector swizzleMethod:(nonnull SEL)swizzleSelector withBlock:(nonnull id)swizzleBlock;
Parameters
originalSelector
原始方法
swizzleSelector
交换方法
swizzleBlock
实现block
Return Value
是否成功
-
生成原始方法对应的随机交换方法
Declaration
Objective-C
+ (nonnull SEL)fw_exchangeSwizzleSelector:(nonnull SEL)selector;
Parameters
selector
原始方法
Return Value
交换方法
-
通用swizzle替换方法为block实现,支持类和对象,identifier有值且相同时仅执行一次。复杂情况不会冲突,推荐使用
Declaration
Objective-C
+ (BOOL)fw_swizzleMethod:(nullable id)target selector:(nonnull SEL)originalSelector identifier:(nullable NSString *)identifier withBlock:(nonnull id _Nonnull (^)( __unsafe_unretained Class _Nonnull, SEL _Nonnull, IMP _Nonnull (^_Nonnull __strong)(void)))block;
Parameters
target
目标类或对象
originalSelector
原始方法
identifier
唯一标识,有值且相同时仅执行一次
block
实现句柄
Return Value
是否成功
-
使用swizzle替换类实例方法为block实现。复杂情况不会冲突,推荐使用
Note
Swift实现代码示例: NSObject.fw.swizzleInstanceMethod(UIViewController.self, selector: NSSelectorFromString(“viewDidLoad”)) { targetClass, originalCMD, originalIMP in let swizzleIMP: @convention(block)(UIViewController) -> Void = { selfObject in typealias originalMSGType = @convention©(UIViewController, Selector) -> Void let originalMSG: originalMSGType = unsafeBitCast(originalIMP(), to: originalMSGType.self) originalMSG(selfObject, originalCMD)
// ... } return unsafeBitCast(swizzleIMP, to: AnyObject.self)
}
Declaration
Objective-C
+ (BOOL)fw_swizzleInstanceMethod:(nonnull Class)originalClass selector:(nonnull SEL)originalSelector withBlock: (nonnull id _Nonnull (^)( __unsafe_unretained Class _Nonnull, SEL _Nonnull, IMP _Nonnull (^_Nonnull __strong)(void)))block;
Parameters
originalClass
原始类
originalSelector
原始方法
block
实现句柄
Return Value
是否成功
-
使用swizzle替换类静态方法为block实现。复杂情况不会冲突,推荐使用
Declaration
Objective-C
+ (BOOL)fw_swizzleClassMethod:(nonnull Class)originalClass selector:(nonnull SEL)originalSelector withBlock: (nonnull id _Nonnull (^)( __unsafe_unretained Class _Nonnull, SEL _Nonnull, IMP _Nonnull (^_Nonnull __strong)(void)))block;
Parameters
originalClass
原始类
originalSelector
原始方法
block
实现句柄
Return Value
是否成功
-
使用swizzle替换类实例方法为block实现,identifier相同时仅执行一次。复杂情况不会冲突,推荐使用
Declaration
Objective-C
+ (BOOL)fw_swizzleInstanceMethod:(nonnull Class)originalClass selector:(nonnull SEL)originalSelector identifier:(nonnull NSString *)identifier withBlock: (nonnull id _Nonnull (^)( __unsafe_unretained Class _Nonnull, SEL _Nonnull, IMP _Nonnull (^_Nonnull __strong)(void)))block;
Parameters
originalClass
原始类
originalSelector
原始方法
identifier
唯一标识
block
实现句柄
Return Value
是否成功
-
使用swizzle替换类静态方法为block实现,identifier相同时仅执行一次。复杂情况不会冲突,推荐使用
Declaration
Objective-C
+ (BOOL)fw_swizzleClassMethod:(nonnull Class)originalClass selector:(nonnull SEL)originalSelector identifier:(nonnull NSString *)identifier withBlock: (nonnull id _Nonnull (^)( __unsafe_unretained Class _Nonnull, SEL _Nonnull, IMP _Nonnull (^_Nonnull __strong)(void)))block;
Parameters
originalClass
原始类
originalSelector
原始方法
identifier
唯一标识
block
实现句柄
Return Value
是否成功
-
获取类方法列表,自动缓存,支持meta类(objc_getMetaClass)
Declaration
Objective-C
+ (nonnull NSArray<NSString *> *)fw_classMethods:(nonnull Class)clazz superclass:(BOOL)superclass;
Parameters
clazz
指定类
superclass
是否包含父类,包含则递归到NSObject
Return Value
方法列表
-
获取类属性列表,自动缓存,支持meta类(objc_getMetaClass)
Declaration
Objective-C
+ (nonnull NSArray<NSString *> *)fw_classProperties:(nonnull Class)clazz superclass:(BOOL)superclass;
Parameters
clazz
指定类
superclass
是否包含父类,包含则递归到NSObject
Return Value
属性列表
-
获取类Ivar列表,自动缓存,支持meta类(objc_getMetaClass)
Declaration
Objective-C
+ (nonnull NSArray<NSString *> *)fw_classIvars:(nonnull Class)clazz superclass:(BOOL)superclass;
Parameters
clazz
指定类
superclass
是否包含父类,包含则递归到NSObject
Return Value
Ivar列表