[swift学习之十六]RunTime练习一

/*
 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值