/*
1:如果不继承NSObject的话,不能获取objc_property_t和Method的信息。看来要想用好runtime,必须继承NSObject啊~!
*/
class RunTimeTest:NSObject{
override class func description() -> String {
return "RunTimeTest"
}
static var StaticProperty = 0
var StorePropertyStr = "Hello"
var StoreProperty = 1
var CaculateProperty: Int{
get{
return StoreProperty
}
set(newValue){
StoreProperty = newValue
}
}
dynamic func TestMethondFirst() -> Void {
print("\(#function)")
}
dynamic func TestMethondSecond() -> Void {
print("\(#function)")
}
}
/*获取父类名,如果不继承NSObject的话,是swiftobject*/
if class_getSuperclass(RunTimeTest) == NSObject.classForCoder() {
print("父类是NSObject")
}
/*获取实例的大小,不受静态变量的限制。空类是16字节,self应该占8字节,另外的就不知道了。~*/
print("RunTimeTest的实例大小:\(class_getInstanceSize(RunTimeTest))")
/*获取类型
通过class_getName这个方式获得的类型串,前面有个前缀__lldb_expr_1472,不明白啥意思啊~!
但是RunTimeTest.classForCoder().description()也是一样,看来得改下description了。
*/
RunTimeTest.classForCoder().description()
RunTimeTest.self
print(String.fromCString(class_getName(RunTimeTest))!)
/*设置版本,读取版本,不设置的话是0,但不知道这个有什么用~~!*/
class_getVersion(RunTimeTest)//0
RunTimeTest.setVersion(8)
class_getVersion(RunTimeTest)//8
/*获取元类*/
objc_getMetaClass(class_getName(RunTimeTest.self))
/*获取全部成员变量信息*/
var iVarCount: UInt32 = 0
let ivarArr:UnsafeMutablePointer<Ivar> = class_copyIvarList(RunTimeTest.self, &iVarCount)
var CurrIvar:UnsafeMutablePointer<Ivar> = ivarArr
for _ in 1...iVarCount{
ivar_getOffset(CurrIvar.memory)
print(String.fromCString(ivar_getName(CurrIvar.memory)))
CurrIvar = ivarArr.successor()
}
/*获取全部属性信息,注意,这里包括计算属性和存储属性。
property_getAttributes 的结果是“T@\\"NSString\\",N,C,VStorePropertyStr”
没读懂这个信息的具体含义
~*/
let PropArr:UnsafeMutablePointer<objc_property_t> = class_copyPropertyList(RunTimeTest.self, &iVarCount)
var CurrProp:UnsafeMutablePointer<objc_property_t> = PropArr
for _ in 1...iVarCount{
print(String.fromCString(property_getName(CurrProp.memory)))
print(String.fromCString(property_getAttributes(CurrProp.memory)))
CurrProp = PropArr.successor()
}
/*获取全部的方法信息*/
let MethodArr:UnsafeMutablePointer<Method> = class_copyMethodList(RunTimeTest.self, &iVarCount)
var CurrMethod:UnsafeMutablePointer<Method> = MethodArr
for _ in 1...iVarCount{
print(NSStringFromSelector(method_getName(CurrMethod.memory)))
let MethodType = method_getDescription(CurrMethod.memory).memory.types
print(String.fromCString(MethodType))
/*这个地方居然能运行,而且还能得到正确的方法签名MethodType,不可思议啊~!*/
print(String.fromCString(property_getAttributes(CurrMethod.memory)))
CurrMethod = CurrMethod.successor()
}
/*上面的三个循环的结果如下,protocol的就不试验了,过程都一样~!
-----成员变量------
Optional("StorePropertyStr")
Optional("StoreProperty")
-----全部属性------
Optional("StorePropertyStr")
Optional("T@\"NSString\",N,C,VStorePropertyStr")
Optional("StoreProperty")
Optional("Tq,N,VStoreProperty")
Optional("StoreProperty")
Optional("Tq,N,VStoreProperty")
-----全部方法------
StorePropertyStr
Optional("@16@0:8")
setStorePropertyStr:
Optional("v24@0:8@16")
StoreProperty
Optional("q16@0:8")
setStoreProperty:
Optional("v24@0:8q16")
CaculateProperty
Optional("q16@0:8")
setCaculateProperty:
Optional("v24@0:8q16")
.cxx_destruct
Optional("@?")
init
Optional("@16@0:8")
*/
/*实例部分*/
let InstanceRun = RunTimeTest()
/*获取类型信息*/
objc_getClass(class_getName(RunTimeTest))
InstanceRun.classForCoder.description()
/*获取某一存储属性信息,COpaquePointer这个玩意就是void*吧~!
1,这里指针对存储属性,计算属性为nil。
2,ivar_getOffset偏移字节数,空类为16字节,不受计算属性及函数影响。
*/
let iVarPro:Ivar = class_getInstanceVariable(InstanceRun.classForCoder, "StorePropertyStr")
print(String.fromCString(ivar_getName(iVarPro)))
ivar_getOffset(iVarPro)
/*获取类中实例的方法*/
let SecondMethod = class_getInstanceMethod(RunTimeTest.self, NSSelectorFromString("TestMethondSecond"))
/*获取类中实例的方法的指针*/
let ImpSecond = method_getImplementation(SecondMethod)
/*和下面等价*/
//let ImpSecond = class_getMethodImplementation(InstanceRun.classForCoder, NSSelectorFromString("TestMethondSecond"))
/*替代原有方法*/
class_replaceMethod(InstanceRun.classForCoder, NSSelectorFromString("TestMethondFirst"), ImpSecond, method_getDescription(SecondMethod).memory.types)
/*
1,这里被替换的函数必须是dynamic的,否则没有效果,找半天才找到~!
2,下面一段话,是讲的为什么dynamic的函数才能实现动态替换,没怎么看明白~~!
方法调配是替换一个已存在的方法实现。Swift优化后,不再像Objective-C中那样,在runtime寻找方法的位置,而是直接调用内存地址。因此默认情况下,在Swift类中调配无法起效,除非:
用动态关键字禁用这种优化。这是最佳选择,如果数据库完全以Swift构建的话,这种选择也是最合理的方式。
扩展NSObject。如果单纯为了方法调配的话,不要用这种方式(而要采用动态的)。需要了解:在将NSObject作为基础类的已存在类中,方法调配是有效的,不过最好使用动态选择的方法。
在要调配的方法中使用@objc注释。如果我们想要调配的方法同时也需要使用Objective-C的代码,那么这种方法是最合适的
3,通过Swift执行方法调用要比使用Objective-C快四倍。
*/
InstanceRun.TestMethondFirst()//结果:TestMethondSecond()
还有其他内容没有练习,如动态创建类,添加方法等。下一篇继续。
参考:http://blog.jobbole.com/79566/
http://www.tuicool.com/articles/ArYbuaJ