objc_getAssociatedObject
objc_setAssociatedObject
objc_allocateClassPair 新注册一个类,为类添加方法
objc_registerClassPair
_objc_msgForward
objc_allocateProtocol
objc_registerProtocol
objc_getProtocol
objc_getMetaClass
_objc_msgForward_stret
objc_msgSend
object_getClass 获取obj的isa指向 char*转化Class
object_setClass 强制设置obj的isa指向
class_getInstanceMethod 获取类的实例方法
class_getSuperclass 获取类的父类
class_replaceMethod 替换某个类的方法为新的实现
class_addMethod
Adds a new method to a class with a given name and implementation.
class_addMethod will add an override of a superclass's implementation, but will not replace an existing implementation in this class. To change an existing implementation, use method_setImplementation.
cls
The class to which to add a method.
name
A selector that specifies the name of the method being added.
class_respondsToSelector
class_getMethodImplementation
class_isMetaClass
class_addProtocol
method_getImplementation
method_getTypeEncoding
method_exchangeImplementations
protocol_addMethodDescription
protocol_copyMethodDescriptionList
Sel
Method
Protocol
Class
NSMethodSignature
子类/重写几个方法
1、RAC的Selector实现原理
创建一个全新的类型; 交换下面的几个方法:
forwardInvocation
respondsToSelector
class
methodSignatureForSelector
2、系统的KVO的实现原理
子类;
3、RAC的swizzleDeallocIfNeeded实现原理
方法交换;
4、RAC的KVO
支持同时实现RAC的SwizzleSelector和RACObserve,这么用没问题。
但是dealloc的SwizzleSelector和dealloc的swizzleDeallocIfNeeded同时实现会发生crash!
[[self rac_signalForSelector:@selector(setKvoValue:)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"11111 %@", x);
}];
[[RACKVOTrampoline alloc] initWithTarget:self observer:self keyPath:@keypath(self.kvoValue) options:NSKeyValueObservingOptionInitial|NSKeyValueObservingOptionNew block:^(id target, id observer, NSDictionary *change) {
NSLog(@"22222 %@,%@, %@", change, target, observer);
}];
Method method = class_getInstanceMethod(self.class, @selector(timerfirep:));
char const objctypes = method_getTypeEncoding(method);
//[NSMethodSignature signatureWithObjCTypes:]: type signature is NULL.'
NSMethodSignaturemsign= // [self methodSignatureForSelector:@selector(timerfirep:)];
// [NSMethodSignature methodSignatureForSelector:@selector(timerfirep:)];
//[NSMethodSignature instanceMethodSignatureForSelector:@selector(timerfirep:)];
[NSMethodSignature signatureWithObjCTypes:objctypes];
NSInvocation*ivok= [NSInvocation invocationWithMethodSignature:msign];
ivok.selector =@selector(timerfirep:);
ivok.target=self;
[ivok setArgument:@"aa" atIndex:2];
[ivok invoke];
__unsafe_unretained id aa;
[ivok getReturnValue:&aa];
5、RacBlockTrampoline 与 NSInvocation
performSelector
参数限制:
1、支持最多两个参数。
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
2、返回类型限制:
如果aSelector返回c基本数据类型(非id对象数据类型), 则此调用会崩溃。 入口参数也只能是id类型。
3、libDispatch库、如果perferm到主线程提交, 则由runloop+timer (runloop组成:每一个mode的item有(source、timer 、observer组成))实现。
NSInvocation
应用1; RACBlockTrampoline----Block不支持:基本数据类型的参数和返回值
-
(__kindof RACStream *)reduceEach:(id (^)())reduceBlock {
NSCParameterAssert(reduceBlock != nil);__weak RACStream *stream attribute((unused)) = self;
return [[self map:^(RACTuple *t) {
NSCAssert([t isKindOfClass:RACTuple.class], @"Value from stream %@ is not a tuple: %@", stream, t);
/// Block不支持:基本数据类型的参数和返回值
return [RACBlockTrampoline invokeBlock:reduceBlock withArguments:t];
}] setNameWithFormat:@"[%@] -reduceEach:", self.name];
}
-
(id)invokeWithArguments:(RACTuple *)arguments {
SEL selector = [self selectorForArgumentCount:arguments.count];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:selector]];
invocation.selector = selector;
invocation.target = self;for (NSUInteger i = 0; i < arguments.count; i++) {
id arg = arguments[i];
NSInteger argIndex = (NSInteger)(i + 2);
[invocation setArgument:&arg atIndex:argIndex];
}[invocation invoke];
__unsafe_unretained id returnVal;
[invocation getReturnValue:&returnVal];
return returnVal;
}
应用2: ----支持基本数据类型的参数
[[self rac_signalForSelector:@selector(intValue1:float2:char:)] subscribeNext:^(RACTuple * _Nullable x) {
NSLog(@"111-> %@" , x);
} error:^(NSError * _Nullable error) {
NSLog(@"222->: %@" ,error );
} completed:^{
NSLog(@"completed!!");
}];
static BOOL RACForwardInvocation(id self, NSInvocation *invocation) {
SEL aliasSelector = RACAliasForSelector(invocation.selector);
RACSubject *subject = objc_getAssociatedObject(self, aliasSelector);
Class class = object_getClass(invocation.target);
BOOL respondsToAlias = [class instancesRespondToSelector:aliasSelector];
if (respondsToAlias) {
invocation.selector = aliasSelector;
[invocation invoke];
}
if (subject == nil) return respondsToAlias;
///支持基本数据类型的参数
[subject sendNext:invocation.rac_argumentsTuple];
return YES;
}
- (RACTuple *)rac_argumentsTuple {
NSUInteger numberOfArguments = self.methodSignature.numberOfArguments;
NSMutableArray *argumentsArray = [NSMutableArray arrayWithCapacity:numberOfArguments - 2];
for (NSUInteger index = 2; index < numberOfArguments; index++) {
/// Rac实现的自动转化类型 -----NSInvocation+RACTypeParsing.h
//d, f, Q, I 等。 。CGFloat对应Double 转化过程rac_argumentAtIndex
// NSLog(@"%s, %s, %s, %s", @encode(CGFloat), @encode(float), @encode(NSUInteger), @encode(unsigned int));
[argumentsArray addObject:[self rac_argumentAtIndex:index] ?: RACTupleNil.tupleNil];
}
return [RACTuple tupleWithObjectsFromArray:argumentsArray];
}
应用3: -------
// methodSignature 的numberOfArguments已经包括了target和selector了的个数了
NSMethodSignature *methodSignature = [self methodSignatureForSelector:@selector(intValue1:float2:char:)] ;
NSInvocation*invocation = [NSInvocation invocationWithMethodSignature:methodSignature];
RACTuple *argumentTuple= [RACTuple tupleWithObjects:@"1",@"1.2",@"122", nil];
// Rac实现的自动转化类型
invocation.rac_argumentsTuple = argumentTuple;
// 自己实现需要这样 ---
// 基本数据类型:char,int,short,long,long long,unsigned char, unsigned int, unsigned short, unsigned long, unsigned long long,float, double, bool, char *
// block,id ,Class类型
// NSValue类型
int intValue1 = [argumentTuple[0] intValue];
float floatValue = [argumentTuple[1] floatValue];
const char *charValue = [argumentTuple[2] UTF8String];
[invocation setArgument:&(intValue1) atIndex:2];
[invocation setArgument:&(floatValue) atIndex:3];
[invocation setArgument:&charValue atIndex:4];
// (lldb) po invocation.selector
//
//(lldb) po invocation.target
//nil
//此时target和selector还都是空。所以要赋值
invocation.selector =@selector(intValue1:float2:char:);
invocation.target=self;
[invocation invoke];
__unsafe_unretained id aa;
// Rac实现基本数据类型的转换
aa =[invocation rac_returnValue];
// 自己实现需要这样 ---
// 基本数据类型:char,int,short,long,long long,unsigned char, unsigned int, unsigned short, unsigned long, unsigned long long,float, double, bool, char *
// block,id ,Class类型
// NSValue类型
int aReturnValue = 0;
[invocation getReturnValue:&aReturnValue];
NSLog(@"%@ , %d", aa, aReturnValue);
-(int )intValue1:(int )int1 float2:(float)float2 char:(char *)char3 {
NSLog(@"NSInvocation调用成功:%d , %f, %s ", int1, float2, char3);
return 1;
}
void 类型:void
block类型:void (^)(void)
对象类型:id,Class,
基本数据类型:char,int,short,long,long long(NSInteger),unsigned char, unsigned int, unsigned short, unsigned long, unsigned long long(NSUInteger),float, double(CGFloat), bool, char *
数值类型 8种类型:需要用NSValue转换。CGPoint,CGVector,CGSize,CGRect,CGAffineTransform,UIEdgeInsets, NSDirectionalEdgeInsets,UIOffset
SEL sel =@selector(intValue1:cgfloat2:char:cgpoint:);
NSMethodSignature *signature = [self methodSignatureForSelector:sel ];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature ];
invocation.selector = sel ;
invocation.rac_argumentsTuple = RACTuplePack(@"12345",@(1.2),@"12122",[NSValue valueWithCGPoint:CGPointMake(12, 122)]);
[invocation invokeWithTarget:self];
NSValue*pointValue= [invocation rac_returnValue];
NSLog(@"%@",NSStringFromCGPoint( [pointValue CGPointValue]));
-(CGPoint )intValue1:(int )int1 cgfloat2:(CGFloat)float2 char:(const char *)char3 cgpoint:(CGPoint)point4 {
NSLog(@"NSInvocation调用成功:%d , %f, %s , %@", int1, float2, char3, NSStringFromCGPoint(point4));
return CGPointMake(100, 100);
}
- (void)rac_setArgument:(id)object atIndex:(NSUInteger)index {
define PULL_AND_SET(type, selector) \
do { \
type val = [object selector]; \
[self setArgument:&val atIndex:(NSInteger)index]; \
} while (0)
const char *argType = [self.methodSignature getArgumentTypeAtIndex:index];
// Skip const type qualifier.
if (argType[0] == 'r') {
argType++;
}
if (strcmp(argType, @encode(id)) == 0 || strcmp(argType, @encode(Class)) == 0) {
[self setArgument:&object atIndex:(NSInteger)index];
} else if (strcmp(argType, @encode(char)) == 0) {
PULL_AND_SET(char, charValue);
} else if (strcmp(argType, @encode(int)) == 0) {
PULL_AND_SET(int, intValue);
} else if (strcmp(argType, @encode(short)) == 0) {
PULL_AND_SET(short, shortValue);
} else if (strcmp(argType, @encode(long)) == 0) {
PULL_AND_SET(long, longValue);
} else if (strcmp(argType, @encode(long long)) == 0) {
PULL_AND_SET(long long, longLongValue);
} else if (strcmp(argType, @encode(unsigned char)) == 0) {
PULL_AND_SET(unsigned char, unsignedCharValue);
} else if (strcmp(argType, @encode(unsigned int)) == 0) {
PULL_AND_SET(unsigned int, unsignedIntValue);
} else if (strcmp(argType, @encode(unsigned short)) == 0) {
PULL_AND_SET(unsigned short, unsignedShortValue);
} else if (strcmp(argType, @encode(unsigned long)) == 0) {
PULL_AND_SET(unsigned long, unsignedLongValue);
} else if (strcmp(argType, @encode(unsigned long long)) == 0) {
PULL_AND_SET(unsigned long long, unsignedLongLongValue);
} else if (strcmp(argType, @encode(float)) == 0) {
PULL_AND_SET(float, floatValue);
} else if (strcmp(argType, @encode(double)) == 0) {
PULL_AND_SET(double, doubleValue);
} else if (strcmp(argType, @encode(BOOL)) == 0) {
PULL_AND_SET(BOOL, boolValue);
} else if (strcmp(argType, @encode(char *)) == 0) {
const char *cString = [object UTF8String];
[self setArgument:&cString atIndex:(NSInteger)index];
[self retainArguments];
} else if (strcmp(argType, @encode(void (^)(void))) == 0) {
[self setArgument:&object atIndex:(NSInteger)index];
} else {
// CGPoint,CGRect这些类型用NSValue进行参数传入
NSCParameterAssert([object isKindOfClass:NSValue.class]);
NSUInteger valueSize = 0;
NSGetSizeAndAlignment([object objCType], &valueSize, NULL);
if DEBUG
NSUInteger argSize = 0;
NSGetSizeAndAlignment(argType, &argSize, NULL);
NSCAssert(valueSize == argSize, @"Value size does not match argument size in -rac_setArgument: %@ atIndex: %lu", object, (unsigned long)index);
endif
unsigned char valueBytes[valueSize];
[object getValue:valueBytes];
[self setArgument:valueBytes atIndex:(NSInteger)index];
}
undef PULL_AND_SET
}