温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》
  • 首页 > 
  • 教程 > 
  • 开发技术 > 
  • dynamic动态分发,unsafeBitCast,自动调用的闭包-设置时,会设置一个KVO监听

dynamic动态分发,unsafeBitCast,自动调用的闭包-设置时,会设置一个KVO监听

发布时间:2020-08-22 01:27:31 来源:网络 阅读:1795 作者:iOS技术者 栏目:开发技术

//MARK: - 主题更改时,自动执行

extension NSObject {

    fileprivate struct AssociatedKeys {

        static var thmemChanged = "thmemChanged"

    }

    

    /// 当前主题更改时、第一次设置时 自动调用的闭包

    public typealias ThemeChangedClosure = @convention(block) (_ style:String) -> Void

    

    /// 自动调用的闭包

    /// 设置时,会设置一个KVO监听,当V2Style.style更改时、第一次赋值时 会自动调用这个闭包

    var thmemChangedHandler:ThemeChangedClosure? {

        get {

            let closureObject: AnyObject? = objc_getAssociatedObject(self, &AssociatedKeys.thmemChanged) as AnyObject?

            guard closureObject != nil else{

                return nil

            }

            let closure = unsafeBitCast(closureObject, to: ThemeChangedClosure.self)

            return closure

        }

        set{

            guard let value = newValue else{

                return

            }

            let dealObject: AnyObject = unsafeBitCast(value, to: AnyObject.self)

            objc_setAssociatedObject(self, &AssociatedKeys.thmemChanged,dealObject,objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

            //设置KVO监听

            self.kvoController.observe(V2EXColor.sharedInstance, keyPath: "style", options: [.initial,.new] , block: {[weak self] (nav, color, change) -> Void in

                self?.thmemChangedHandler?(V2EXColor.sharedInstance.style)

                }

            )

        }

    }

}




class V2EXColor :NSObject  {

    fileprivate static let STYLE_KEY = "styleKey"

    

    static let V2EXColorStyleDefault = "Default"

    static let V2EXColorStyleDark = "Dark"

    

    fileprivate static var _colors:V2EXColorProtocol?

    static var colors :V2EXColorProtocol {

        get{

            

            if let c = V2EXColor._colors {

                return c

            }

            else{

                if V2EXColor.sharedInstance.style == V2EXColor.V2EXColorStyleDefault{

                    return V2EXDefaultColor.sharedInstance

                }

                else{

                    return V2EXDarkColor.sharedInstance

                }

            }

            

        }

        set{

            V2EXColor._colors = newValue

        }

    }

    

    dynamic var style:String

    static let sharedInstance = V2EXColor()

    fileprivate override init(){

        if let style = V2EXSettings.sharedInstance[V2EXColor.STYLE_KEY] {

            self.style = style

        }

        else{

            self.style = V2EXColor.V2EXColorStyleDefault

        }

        super.init()

    }

    func setStyleAndSave(_ style:String){

        if self.style == style {

            return

        }

        

        if style == V2EXColor.V2EXColorStyleDefault {

            V2EXColor.colors = V2EXDefaultColor.sharedInstance

        }

        else{

            V2EXColor.colors = V2EXDarkColor.sharedInstance

        }

        

        self.style = style

        V2EXSettings.sharedInstance[V2EXColor.STYLE_KEY] = style

    }

    

}



dynamic关键字

如果您有过OC的开发经验,那一定会对OC中@dynamic关键字比较熟悉,它告诉编译器不要为属性合成getter和setter方法。

Swift中也有dynamic关键字,它可以用于修饰变量或函数,它的意思也与OC完全不同。它告诉编译器使用动态分发而不是静态分发。OC区别于其他语言的一个特点在于它的动态性,任何方法调用实际上都是消息分发,而Swift则尽可能做到静态分发。

因此,标记为dynamic的变量/函数会隐式的加上@objc关键字,它会使用OC的runtime机制。

虽然静态分发在效率上可能更好,不过一些app分析统计的库需要依赖动态分发的特性,动态的添加一些统计代码,这一点在Swift的静态分发机制下很难完成。这种情况下,虽然使用dynamic关键字会牺牲因为使用静态分发而获得的一些性能优化,但也依然是值得的。

class Kraken {    dynamic var imADynamicallyDispatchedString: String

    dynamic func imADynamicallyDispatchedFunction() {        //Hooray for dynamic dispatch!
    }
}

使用动态分发,您可以更好的与OC中runtime的一些特性(如CoreData,KVC/KVO)进行交互,不过如果您不能确定变量或函数会被动态的修改、添加或使用了Method-Swizzle,那么就不应该使用dynamic关键字,否则有可能程序崩溃。



向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI