动态创建类/ swizzle class
动态创建类
Class subclass = objc_allocateClassPair(baseClass, subclassName, );//生成,指定父类
//添加方法,变量...一些操作
//swizzle消息转发机制
RACSwizzleForwardInvocation(subclass);
RACSwizzleRespondsToSelector(subclass);
//改变class
RACSwizzleGetClass(subclass, statedClass);
RACSwizzleGetClass(object_getClass(subclass), statedClass); RACSwizzleMethodSignatureForSelector(subclass);
objc_registerClassPair(subclass); //注册
object_setClass(self, subclass);//设置isa指针
SwizzleGetClass
static void RACSwizzleGetClass(Class class, Class statedClass) {
SEL selector = @selector(class);
Method method = class_getInstanceMethod(class, selector);
IMP newIMP = imp_implementationWithBlock(^(id self) {
return statedClass;
});
class_replaceMethod(class, selector, newIMP, method_getTypeEncoding(method));
}
SwizzleForwardInvocation
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;
}
static void RACSwizzleForwardInvocation(Class class) {
SEL forwardInvocationSEL = @selector(forwardInvocation:);
Method forwardInvocationMethod = class_getInstanceMethod(class, forwardInvocationSEL);
// Preserve any existing implementation of -forwardInvocation:.
void (*originalForwardInvocation)(id, SEL, NSInvocation *) = NULL;
if (forwardInvocationMethod != NULL) {
originalForwardInvocation = (__typeof__(originalForwardInvocation))method_getImplementation(forwardInvocationMethod);
}
// Set up a new version of -forwardInvocation:.
//
// If the selector has been passed to -rac_signalForSelector:, invoke
// the aliased method, and forward the arguments to any attached signals.
//
// If the selector has not been passed to -rac_signalForSelector:,
// invoke any existing implementation of -forwardInvocation:. If there
// was no existing implementation, throw an unrecognized selector
// exception.
id newForwardInvocation = ^(id self, NSInvocation *invocation) {
BOOL matched = RACForwardInvocation(self, invocation);
if (matched) return;
if (originalForwardInvocation == NULL) {
[self doesNotRecognizeSelector:invocation.selector];
} else {
originalForwardInvocation(self, forwardInvocationSEL, invocation);
}
};
class_replaceMethod(class, forwardInvocationSEL, imp_implementationWithBlock(newForwardInvocation), "v@:@");
}
SwizzleMethodSignatureForSelector
static void RACSwizzleMethodSignatureForSelector(Class class) {
IMP newIMP = imp_implementationWithBlock(^(id self, SEL selector) {
// Don't send the -class message to the receiver because we've changed
// that to return the original class.
Class actualClass = object_getClass(self);
Method method = class_getInstanceMethod(actualClass, selector);
if (method == NULL) {
// Messages that the original class dynamically implements fall
// here.
//
// Call the original class' -methodSignatureForSelector:.
struct objc_super target = {
.super_class = class_getSuperclass(class),
.receiver = self,
};
NSMethodSignature * (*messageSend)(struct objc_super *, SEL, SEL) = (__typeof__(messageSend))objc_msgSendSuper;
return messageSend(&target, @selector(methodSignatureForSelector:), selector);
}
char const *encoding = method_getTypeEncoding(method);
return [NSMethodSignature signatureWithObjCTypes:encoding];
});
SEL selector = @selector(methodSignatureForSelector:);
Method methodSignatureForSelectorMethod = class_getInstanceMethod(class, selector);
class_replaceMethod(class, selector, newIMP, method_getTypeEncoding(methodSignatureForSelectorMethod));
}
SwizzleRespondsToSelector
static void RACSwizzleRespondsToSelector(Class class) {
SEL respondsToSelectorSEL = @selector(respondsToSelector:);
// Preserve existing implementation of -respondsToSelector:.
Method respondsToSelectorMethod = class_getInstanceMethod(class, respondsToSelectorSEL);
BOOL (*originalRespondsToSelector)(id, SEL, SEL) = (__typeof__(originalRespondsToSelector))method_getImplementation(respondsToSelectorMethod);
// Set up a new version of -respondsToSelector: that returns YES for methods
// added by -rac_signalForSelector:.
//
// If the selector has a method defined on the receiver's actual class, and
// if that method's implementation is _objc_msgForward, then returns whether
// the instance has a signal for the selector.
// Otherwise, call the original -respondsToSelector:.
id newRespondsToSelector = ^ BOOL (id self, SEL selector) {
Method method = rac_getImmediateInstanceMethod(class, selector);
if (method != NULL && method_getImplementation(method) == _objc_msgForward) {
SEL aliasSelector = RACAliasForSelector(selector);
if (objc_getAssociatedObject(self, aliasSelector) != nil) return YES;
}
return originalRespondsToSelector(self, respondsToSelectorSEL, selector);
};
class_replaceMethod(class, respondsToSelectorSEL, imp_implementationWithBlock(newRespondsToSelector), method_getTypeEncoding(respondsToSelectorMethod));
}
动态创建类/ swizzle class的更多相关文章
- ios动态创建类Class
[Objective-C Runtime动态加载]---动态创建类Class 动态创建类Class,动态添加Class成员变量与成员函数,动态变量赋值与取值,动态函数调用等方法 a.使用objc_al ...
- python动态创建类的声明
动态创建类的声明 使用内置函数type,原型:class type(name, bases, dict)name是类的名字,相当于__class__bases是类的基类,元组,可以有多个基类,但是基类 ...
- OC 反射-->动态创建类
系统方法 NSLog(@"%s", __func__); //打印出类的方法名称,如: //打印结果:2018-02-22 10:52:15.394575+0800 DemoRun ...
- 使用python type动态创建类
使用python type动态创建类 X = type('X', (object,), dict(a=1)) # 产生一个新的类型 X 和下列方法class X(object): a = 1效 ...
- Python中type()详解:动态创建类
众所周知: type()函数可以查看变量的类型: 先看一个简单的列子来看一下type查看变量类型 class Animal(): pass a=Animal() print(type(a)) prin ...
- python-获取类名和方法名,动态创建类和方法及属性
获取类名和方法名1.在函数外部获取函数名称,用.__name__获取2.在函数内部获取当前函数名称,用sys._getframe().f_code.co_name方法获取3.使用inspect模块动态 ...
- type动态创建类
在一些特定场合,需要动态创建类,比如创建表单,就会用到type动态创建类,举个例子: class Person(object): def __init__(self,name,age): self.n ...
- 深入浅出Cocoa 之动态创建类【转】
在前文<深入浅出Cocoa之类与对象>一文中,我已经详细介绍了ObjC中的 Class 与 Object 的概念,今天我们来如何在运行 时动态创建类.下面这个函数就是应用前面讲到的Clas ...
- Python 中使用动态创建类属性的机制实现接口之后的依赖
我们在自动化测试中经常会需要关联用例处理,需要动态类属性: 推荐使用第二种方法: 创建:setattr() 获取:getattr() 两种,如何创建 类属性 loan_id # 第一种,创建 # 类名 ...
随机推荐
- 普通ACL访问控制列表
配置OSPF R1: R2: R3: R4: 在R1上查看OSPF的学习 测试R1与R4环回接口连通性 配置普通ACL访问控制列表: 先在R4配置密码用R1与R4建立telnet建立 密码huawei ...
- 什么是php扩展
PHP扩展英文为PHP Extension and Application Repository,简称pear(下面都以pear简称),中文全称为PHP扩展与应用库.是为了创建一个类似于Perl CP ...
- [Codeforces 639F] Bear and Chemistry (Tarjan+虚树)(有详细注释)
[Codeforces 639F] Bear and Chemistry(Tarjan+虚树) 题面 给出一个n个点,m条边的无向图(不保证连通,可能有自环和重边),有q次询问,每次询问给出p个点和q ...
- Linux忘记密码怎么办
重启 Linux 系统主机并出现引导界面时,按下键盘上的 e 键进入内核编辑界面 在 linux16 参数这行的最后面追加"rd.break"参数,然后按下 Ctrl + X 组合 ...
- Pandas案例--人口密度分析
需求: 导入文件,查看原始数据 将人口数据和各州简称数据进行合并 将合并的数据中重复的abbreviation列进行删除 查看存在缺失数据的列 找到有哪些state/region使得state的值为N ...
- java中关于异常的处理
初学java的时候,当我们碰到异常时,一般会把异常直接throws抛出去,或则在catch的时候,简单的写一句打印异常信息,但是在实际开发中,是不能这么做的.如果我们将底层的某一个异常简单的print ...
- Linux学习笔记1-在CentOS 7中安装配置JDK8
说明: 参考博客:http://blog.csdn.net/czmchen/article/details/41047187系统环境:CentOS 7安装方式:rpm安装JDK地址:http://ww ...
- 使用join和CountDownLatch来等待线程结束
1.join方法的实现 join只能在start()之后调用, join 某个线程A,会使当前线程B进入等待,直到线程A结束生命周期(isAlive()==false) ,或者达到给定的时间. 在此期 ...
- 笔记--NS_SWIFT_NAME与@objc区别与用途
swift中使用Selector经常要在方法前面添加@objc,除了默认的@objc,其实我们还可以添加自己制定的swift中调用的函数名 @objc(pushToControllerName:par ...
- windows H2database 安装
转载百度经验 H2是一个开源的.纯java实现的关系数据库,小巧并且使用方便,十分适合作为嵌入式数据库使用 首先打开浏览器进入H2官网http://www.h2database.com/html/ma ...