Runtime(swift)使用

一氛赐、runtime介紹、OC的使用

關(guān)于runtime的介紹先舷,和OC的使用艰管,這里就不再去介紹了,大家可以看下以下這兩篇前輩們寫(xiě)的文章蒋川,一篇是runtime的介紹牲芋,一篇是runtime在OC語(yǔ)言下的使用。

1捺球、runtime介紹

2缸浦、runtime OC介紹和使用

二、runtime使用(swift開(kāi)發(fā)環(huán)境)

這里是這篇文章的主要內(nèi)容氮兵,主要介紹swift的編程語(yǔ)言下runtime的使用裂逐。這里重點(diǎn)介紹了runtime常用的三種功能:

提示:
swift運(yùn)用runtime的時(shí)候不需要再導(dǎo)入runtime庫(kù)了。

1泣栈、類拓展添加屬性

思路:

通過(guò)runtime的關(guān)聯(lián)函數(shù)用一個(gè)關(guān)聯(lián)key將需要添加的屬性的值存儲(chǔ)(set方法)獲取(get方法)出來(lái)卜高。

步驟:

  • 1、設(shè)置關(guān)聯(lián)key
  • 2南片、定義要添加的屬性
  • 3掺涛、重寫(xiě)屬性的set和get方法
  • 4、set和get方法中需要調(diào)用runtime的關(guān)聯(lián)函數(shù)

** 代碼實(shí)現(xiàn) **

// 屬性關(guān)聯(lián)的key
private var newPropertyKey = "toNewPropertyKey"

extension ViewController {
    
    var newproperty: String {
        
        // 新添加屬性的set方法
        set(value) {
            /**
             * 第一個(gè)參數(shù):關(guān)聯(lián)的對(duì)象:給哪一個(gè)對(duì)象添加關(guān)聯(lián)疼进,這里就傳哪一個(gè)對(duì)象
             * 第二個(gè)參數(shù):關(guān)聯(lián)的key薪缆,通過(guò)這個(gè)key設(shè)置(存儲(chǔ))對(duì)應(yīng)的值,這里定義了一個(gè)newPropertyKey的key
             * 第三個(gè)參數(shù):關(guān)聯(lián)的值伞广,即通過(guò)key所關(guān)聯(lián)的值拣帽,在get方法中獲取的就是這個(gè)值
             * 第四個(gè)參數(shù):關(guān)聯(lián)的方式
             */
            objc_setAssociatedObject(self, &newPropertyKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
        }
        
        // 新添加屬性的get方法
        get{
            /**
             * 第一個(gè)參數(shù):關(guān)聯(lián)的對(duì)象:給哪一個(gè)對(duì)象添加關(guān)聯(lián),這里就傳哪一個(gè)對(duì)象
             * 第二個(gè)參數(shù):關(guān)聯(lián)的key赔癌,通過(guò)這個(gè)key獲取對(duì)應(yīng)的值
             */
            return objc_getAssociatedObject(self, &newPropertyKey) as! String
        }
    }

    // 測(cè)試這個(gè)新屬性
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 這里可以設(shè)置成功
        newproperty = "newproperty"
        
        // 這里測(cè)試下打印獲取
        print(newproperty)
        
        // 打印結(jié)果:
           newproperty
    }
}

本人不推薦使用上面的方式定義key,特別OC化诞外。。灾票。建議在swift語(yǔ)言下使用以下方式:

// 利用swift強(qiáng)大的結(jié)構(gòu)體去封裝關(guān)聯(lián)key峡谊,然后用swift典型的鏈?zhǔn)骄幊谭绞接眠@些key

extension ViewController {
    
    // 私有的結(jié)構(gòu)體: 這個(gè)類擴(kuò)展下所有新添加屬性的關(guān)聯(lián)值的keys
    private struct AssociateKeys {
        static var toNewPropertyKey = "toNewPropertyKey" // 關(guān)聯(lián)值的key
    }
    
    
    var newproperty: String {
        
        // 新添加屬性的set方法
        set(value) {
            /**
             * 第一個(gè)參數(shù):關(guān)聯(lián)的對(duì)象:給哪一個(gè)對(duì)象添加關(guān)聯(lián),這里就傳哪一個(gè)對(duì)象
             * 第二個(gè)參數(shù):關(guān)聯(lián)的key刊苍,通過(guò)這個(gè)key設(shè)置(存儲(chǔ))對(duì)應(yīng)的值既们,這里定義了一個(gè)newPropertyKey的key
             * 第三個(gè)參數(shù):關(guān)聯(lián)的值,即通過(guò)key所關(guān)聯(lián)的值正什,在get方法中獲取的就是這個(gè)值
             * 第四個(gè)參數(shù):關(guān)聯(lián)的方式
             */
            objc_setAssociatedObject(self, &AssociateKeys.toNewPropertyKey, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
        }
        
        // 新添加屬性的get方法
        get{
            /**
             * 第一個(gè)參數(shù):關(guān)聯(lián)的對(duì)象:給哪一個(gè)對(duì)象添加關(guān)聯(lián)啥纸,這里就傳哪一個(gè)對(duì)象
             * 第二個(gè)參數(shù):關(guān)聯(lián)的key,通過(guò)這個(gè)key獲取對(duì)應(yīng)的值
             */
            return objc_getAssociatedObject(self, &AssociateKeys.toNewPropertyKey) as! String
        }
    }
    
    // 測(cè)試這個(gè)新屬性
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 這里可以設(shè)置成功
        newproperty = "newproperty"
        
        // 這里測(cè)試下打印獲取
        print(newproperty)
    }
}

引深:

大家常見(jiàn)的MJRefresh(OC)上拉下拉等刷新框架婴氮,就是通過(guò)這種方式斯棒,給tableView添加一個(gè)mj_header盾致、mj_footer

2、交換方法

當(dāng)系統(tǒng)自帶的方法滿足不了你的個(gè)性化需求時(shí)荣暮,這時(shí)候需要在保證系統(tǒng)方法原有的基礎(chǔ)上庭惜,給其拓展一些功能。

滿足這樣的需求有兩種方式:

  • 1穗酥、自定義一個(gè)子類护赊,重寫(xiě)父類的方法,把需要的功能寫(xiě)在里面
  • 2砾跃、用runtime 交換 系統(tǒng)的方法骏啰,在調(diào)用系統(tǒng)方式的時(shí)候其實(shí)是調(diào)用自己定義的方法,然后再在自己定義的方法里調(diào)用系統(tǒng)的那個(gè)方法

特別說(shuō)明

交換方法的載體選擇抽高,OC語(yǔ)言中大家可能會(huì)選擇類方法load()或initialize()方法判耕,但是在swift中,已經(jīng)不允許使用load()方法了翘骂,只能選擇initialize()方法祈秕,這個(gè)類方法會(huì)在對(duì)應(yīng)的類初始化的時(shí)候就會(huì)調(diào)用

實(shí)現(xiàn)思路

  • 1、用Runtime的動(dòng)態(tài)添加方法函數(shù)將原生方法動(dòng)態(tài)添加到自定義的方法地址上
  • 2雏胃、如果1添加成功请毛,再用Runtime的動(dòng)態(tài)添加方法函數(shù)將自定義的方法添加到原生方法的地址上
  • 3、如果添加不成功瞭亮,將這兩個(gè)方法再用方法交換函數(shù)進(jìn)行地址交換:method_exchangeImplementations

代碼實(shí)現(xiàn)

extension UIViewController {
    
    // 初始這個(gè)類的時(shí)候進(jìn)行處理:
    public override class func initialize() {
        
        // 只保證執(zhí)行一次:initialize()這個(gè)方法方仿,只要有UIViewController這個(gè)的子類,都會(huì)調(diào)用一次這個(gè)方法统翩,因此在這里添加一個(gè)線程鎖仙蚜,讓其只執(zhí)行一次足夠。
        struct Static {
            static var token: dispatch_once_t = 0
        }
        // 交換思路:
        // 1厂汗、將原生方法動(dòng)態(tài)添加到自定義的方法地址上
        // 2委粉、如果1添加成功,將自定義的方法添加到原生方法的地址上
        // 3娶桦、如果添加不成功贾节,將這兩個(gè)方法再用方法交換函數(shù)進(jìn)行地址交換:method_exchangeImplementations
        dispatch_once(&Static.token) {
            
            // 獲取兩個(gè)方法
            let originalSelector = #selector(viewWillAppear)
            let swizzledSelector = #selector(nsh_viewWillAppear)
            
            // 通過(guò)Selector獲取方法地址
            let originalMethod = class_getInstanceMethod(self, originalSelector)
            let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
            
            // 將系統(tǒng)的方法動(dòng)態(tài)添加到自定義方法的地址上
            // 參數(shù)說(shuō)明:
            // 第一個(gè)參數(shù):給哪個(gè)類添加方法
            // 第二個(gè)參數(shù):添加方法的方法選擇器
            // 第三個(gè)參數(shù):添加方法的函數(shù)實(shí)現(xiàn)(函數(shù)地址)
            // 第四個(gè)參數(shù):函數(shù)的類型
            let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
            
            // 上一步添加成功,再將自定義的添加到原生方法的地址上
            if didAddMethod {
                class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
            } else {
                // 之前添加不成功衷畦,再交換兩個(gè)方法的地址
                method_exchangeImplementations(originalMethod, swizzledMethod)
            }
        }
    }
    
    // MARK: - Method Swizzling
    
    func nsh_viewWillAppear(animated: Bool) {
        // 調(diào)用自定義的方法去實(shí)現(xiàn)系統(tǒng)原生的方法栗涂,因?yàn)榇藭r(shí)自定義的方法地址已經(jīng)是系統(tǒng)對(duì)應(yīng)方法的地址了
        self.nsh_viewWillAppear(animated)
        
        // TODO:自己想要添加的功能
        print("nsh_viewWillAppear: \(description)")
    }
}

3、遍歷獲取屬性名方法名

  • 獲取屬性名:
 // 記錄屬性的個(gè)數(shù)
 var count : UInt32 = 0
 // 獲取所有屬性祈争、個(gè)數(shù)
 let ivarList = class_copyIvarList(UINavigationController().classForCoder, &count)
 // 遍歷屬性獲取屬性名
 for index in 0...count-1 {
     // 獲取屬性名的C(C語(yǔ)言的字符串)
     let propertyNameC = ivar_getName(ivarList[Int(index)])
     // 將C語(yǔ)言字符串轉(zhuǎn)成Swift語(yǔ)言的字符串
     let propertyName = String.fromCString(propertyNameC)
     // 獲取屬性名的C(C語(yǔ)言的字符串)
     let propertyTypeC = ivar_getTypeEncoding(ivarList[Int(index)])
     // 將C語(yǔ)言字符串轉(zhuǎn)成Swift語(yǔ)言的字符串
     let prorpertyType = String.fromCString(propertyTypeC)
     print(propertyName!,prorpertyType!)
 }
 

打印結(jié)果:


Snip20160911_2.png
  • 獲取方法名:
// 記錄方法名的個(gè)數(shù)
var count : UInt32 = 0
// 獲取所有的方法名
let methods = class_copyMethodList(UIView().classForCoder, &count)
// 遍歷數(shù)組獲取每一個(gè)方法名
for index in 0...count-1 {
    // 獲取方法
    let sel = method_getName(methods[Int(index)])
    // 獲取方法名稱(C語(yǔ)言下的)
    let methodNameC = sel_getName(sel)
    // 將名稱轉(zhuǎn)為swift語(yǔ)言下
    let methodName = String.fromCString(methodNameC)
    print(methodName!)
}

打印結(jié)果(一部分):

Snip20160911_4.png

不斷更新中···

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末斤程,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子菩混,更是在濱河造成了極大的恐慌忿墅,老刑警劉巖扁藕,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異疚脐,居然都是意外死亡纹磺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)亮曹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人秘症,你說(shuō)我怎么就攤上這事照卦。” “怎么了乡摹?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵役耕,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我聪廉,道長(zhǎng)瞬痘,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任板熊,我火速辦了婚禮框全,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘干签。我一直安慰自己津辩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布容劳。 她就那樣靜靜地躺著喘沿,像睡著了一般。 火紅的嫁衣襯著肌膚如雪竭贩。 梳的紋絲不亂的頭發(fā)上蚜印,一...
    開(kāi)封第一講書(shū)人閱讀 50,096評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音留量,去河邊找鬼窄赋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛楼熄,可吹牛的內(nèi)容都是我干的寝凌。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼孝赫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼较木!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起青柄,我...
    開(kāi)封第一講書(shū)人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤伐债,失蹤者是張志新(化名)和其女友劉穎预侯,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體峰锁,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡萎馅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了虹蒋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片糜芳。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖魄衅,靈堂內(nèi)的尸體忽然破棺而出峭竣,到底是詐尸還是另有隱情,我是刑警寧澤晃虫,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布皆撩,位于F島的核電站,受9級(jí)特大地震影響哲银,放射性物質(zhì)發(fā)生泄漏扛吞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一荆责、第九天 我趴在偏房一處隱蔽的房頂上張望滥比。 院中可真熱鬧,春花似錦做院、人聲如沸守呜。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)查乒。三九已至,卻和暖如春郁竟,著一層夾襖步出監(jiān)牢的瞬間玛迄,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工棚亩, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蓖议,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓讥蟆,卻偏偏與公主長(zhǎng)得像勒虾,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瘸彤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)修然、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,066評(píng)論 4 62
  • 有幸參加了易效能天使6班的學(xué)習(xí)。今天是第11天愕宋。非常感動(dòng)玻靡,能和這么一大群積極向上,互相關(guān)愛(ài)中贝,互相監(jiān)督囤捻,共同進(jìn)步的天...
    季開(kāi)宇閱讀 180評(píng)論 1 1
  • 可能每個(gè)人心中都有個(gè)環(huán)球夢(mèng),然而終其一生實(shí)現(xiàn)的卻沒(méi)有幾個(gè)邻寿! 曾經(jīng)我以為環(huán)球旅行這不能稱之為夢(mèng)想蝎土,可今天我發(fā)現(xiàn)這正是...
    張偉健閱讀 382評(píng)論 0 0
  • 不常聯(lián)系的D突然發(fā)信息說(shuō)他做錯(cuò)事了誊涯,不知道怎么辦,很想逃避枝秤,想自殺……我腦子迅速轉(zhuǎn)動(dòng),善良如他慷嗜,必不會(huì)做出...
    杏運(yùn)吧閱讀 522評(píng)論 0 1
  • 做服裝銷售,有很多的銷售技巧缭乘,對(duì)于服裝銷售的技巧沐序,我們或許都知道一點(diǎn),比如我們經(jīng)常會(huì)遇到顧客說(shuō):把零頭抹了我就買(mǎi)堕绩。...
    瘦朵朵教你瘦閱讀 1,569評(píng)論 0 3