国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Swift 中的 Runtime

miracledan / 788人閱讀

摘要:更確切地說,可能在僅使用庫的時候只運(yùn)行。比如說中的就無法向既有類添加屬性。在講解的原文中曾指出出于安全性和一致性的考慮,方法交叉過程永遠(yuǎn)會在方法中進(jìn)行。隨便修改基礎(chǔ)框架或所使用的三方代碼會給項目造成很大的影響。

即使在 Swift APP 中沒有一行 Object-c 的代碼,每個 APP 也都會在 Object-c runtime 中運(yùn)行,為動態(tài)任務(wù)分發(fā)和運(yùn)行時對象關(guān)聯(lián)開啟了一個世界。更確切地說,可能在僅使用 Swift 庫的時候只運(yùn)行 Swift runtime。但是使用 Objective-C runtime 這么長時間,我們也應(yīng)該讓他充分發(fā)揮其作用。

下面我們將以 Swift 的視角來觀察關(guān)聯(lián)對象(associated objects])和方法交叉(method swizzling) 這兩個在運(yùn)行時的技術(shù)。

關(guān)聯(lián)對象(Associated Objects)

Swift extension 可以給已經(jīng)存在 Cocoa 類添加極為豐富的功能,具體有:
(1)添加計算實例屬性 ( computed property) 和計算類屬性

(2)定義實例方法和類方法

(3)提供新的構(gòu)造器

(4)定義下標(biāo)(subscript)

(5)定義和使用新的嵌套類型

(6)使一個遵守某個接口

相比之下, Objective-C 的 category 就遜色多了。比如說 Objective-C 中的 extension 就無法向既有類添加屬性。

慶幸的是 Objective-C 的 關(guān)聯(lián)對象(Associated Objects) 可以改善這個缺憾。例如要向一個工程里所有的 view controllers 中添加一個 descriptiveName 屬性,我們可以簡單的使用 objc_get/setAssociatedObject()來填充其 get 和 set 塊:

Swift

extension UIViewController {
    private struct AssociatedKeys {
        static var DescriptiveName = "nsh_DescriptiveName"
    }

    var descriptiveName: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.DescriptiveName) as? String
        }
        set {
            if let newValue = newValue {
                objc_setAssociatedObject(
                    self,
                    &AssociatedKeys.DescriptiveName,
                    newValue as NSString?,
                    UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                )
            }
        }
    }

注意,在私有嵌套 struct 中使用 static var,這樣會生成我們所需的關(guān)聯(lián)對象鍵,但不會污染整個命名空間。

方法交叉(Method Swizzling)

有時為了方便,也有可能是解決某些框架內(nèi)的 bug,或者別無他法時,需要修改一個已經(jīng)存在類的方法的行為。方法交叉可以實現(xiàn)兩個方法的交換,相當(dāng)于是用你自己寫的方法來重載原有方法,并且還能夠是原有方法的行為保持不變。

下面,我們說一個例子,在這個例子中我們交叉 UIViewController 的 viewWillAppear 方法,然后打印出每一個在屏幕上顯示的 view。方法交叉發(fā)生在 initialize 類方法調(diào)用時(如下代碼所示);替代的實現(xiàn)在 nsh_viewWillAppear 方法中:

Swift
extension UIViewController {
    public override class func initialize() {
        struct Static {
            static var token: dispatch_once_t = 0
        }

        // make sure this isn"t a subclass        
        if self !== UIViewController.self {
            return
        }

        dispatch_once(&Static.token) {
            let originalSelector = Selector("viewWillAppear:")
            let swizzledSelector = Selector("nsh_viewWillAppear:")

            let originalMethod = class_getInstanceMethod(self, originalSelector)
            let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

            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 {
                method_exchangeImplementations(originalMethod, swizzledMethod);
            }
        }
    }

    // MARK: - Method Swizzling

    func nsh_viewWillAppear(animated: Bool) {
        self.nsh_viewWillAppear(animated)
        if let name = self.descriptiveName {
            println("viewWillAppear: (name)")
        } else {
            println("viewWillAppear: (self)")
        }
    }
}

load vs. initialize (Swift 版本)

Objective-C runtime 理論上會在加載和初始化類的時候調(diào)用兩個類方法: load and initialize。在講解 method swizzling 的原文中曾指出出于安全性和一致性的考慮,方法交叉過程 永遠(yuǎn) 會在 load() 方法中進(jìn)行。每一個類在加載時只會調(diào)用一次 load 方法。另一方面,一個 initialize 方法可以被一個類和它所有的子類調(diào)用,比如說 UIViewController 的該方法,如果那個類沒有被傳遞信息,那么它的 initialize 方法就永遠(yuǎn)不會被調(diào)用了。

可不同的是,在 Swift 中 load 類方法是不會被 runtime 調(diào)用,因此 Method Swizzling 就沒有辦法來實現(xiàn),但是,我們有如下兩個方法可以來解決:

1.在 initialize 中實現(xiàn)方法交叉 這種做法很安全,你只需要確保相關(guān)的方法交叉在一個 dispatch_once 中就好了(這也是最推薦的做法)。

2.在 app delegate 中實現(xiàn)方法交叉 不像上面通過類擴(kuò)展進(jìn)行方法交叉,而是簡單地在 app delegate 的 application(_:didFinishLaunchingWithOptions:) 方法調(diào)用時中執(zhí)行相關(guān)代碼也是可以的。基于對類的修改,這種方法應(yīng)該就足夠確保這些代碼會被執(zhí)行到。

最后,提醒大家,在不得已的情況下才去使用 Objective-C runtime。隨便修改基礎(chǔ)框架或所使用的三方代碼會給項目造成很大的影響。請務(wù)必要小心哦。

文章來源:Swift&Object-c Runtime

備注:本文已經(jīng)得到原作者的同意,授權(quán) OneAPM 技術(shù)博客進(jìn)行轉(zhuǎn)載

OneAPM Mobile Insight 以真實用戶體驗為度量標(biāo)準(zhǔn)進(jìn)行 Crash 分析,監(jiān)控網(wǎng)絡(luò)請求及網(wǎng)絡(luò)錯誤,提升用戶留存。訪問 OneAPM 官方網(wǎng)站感受更多應(yīng)用性能優(yōu)化體驗,想閱讀更多技術(shù)文章,請訪問 OneAPM 官方技術(shù)博客。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/17490.html

相關(guān)文章

  • 正在失業(yè)中的《課多周刊》(第3期)

    摘要:正在失業(yè)中的課多周刊第期我們的微信公眾號,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。若有幫助,請把課多周刊推薦給你的朋友,你的支持是我們最大的動力。是一種禍害譯本文淺談了在中關(guān)于的不好之處。淺談超時一運(yùn)維的排查方式。 正在失業(yè)中的《課多周刊》(第3期) 我們的微信公眾號:fed-talk,更多精彩內(nèi)容皆在微信公眾號,歡迎關(guān)注。 若有幫助,請把 課多周刊 推薦給你的朋友,你的支持是我們最大的...

    robin 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<