Swift   发布时间:2022-03-31  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了Swift 扩展「可以」添加存储属性大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

概述

作者:Tikitu de Jager,原文链接,原文日期:2015-10-31 译者:Darren;校对:Cee;定稿:CMB 好吧,其实我标题党了:Swift 扩展只能添加计算属性。然而如果你愿意用 Objective-C 的关联对象,你可以在 Swift 中做一些同样有趣的事。有很多的模板可供选择,然而如果你用这些太过显然的方式,你也就牺牲了类型安全。我们可以做得更好吗? 当然可以。这里就是一

好吧,其实我标题党了:Swift 扩展只能添加计算属性。然而如果你愿意用 Objective-C 的关联对象,你可以在 Swift 中做一些同样有趣的事。有很多的模板可供选择,然而如果你用这些太过显然的方式,你也就牺牲了类型安全。我们可以做得更好吗?

当然可以。这里就是一些这样的函数,使用 Swift 类型推断的黑魔法,使你在类或协议扩展中写类型安全的非 Optional 计算属性时,就像存储属性一样。

import Foundation
func associatedObject<ValueType: AnyObject>(
        base: AnyObject,key: UnsafePointer<UInt8>,initialiser: () -> ValueTypE) 
        -> ValueType {
    if let associated = objc_getAssociatedObject(base,key) 
        as? ValueType { return associated }
    let associated = initialiser()
    objc_setAssociatedObject(base,key,associated,.oBJC_ASSOCIATION_RETAIN)
    return associated
}
func associateObject<ValueType: AnyObject>(
        base: AnyObject,value: ValueTypE) {
    objc_setAssociatedObject(base,value,.oBJC_ASSOCIATION_RETAIN)
}

函数就那么长。你可以这样使用它们:

class Miller {} // 这是我们要扩展的类
class Cat { // 每个磨坊主都有一只猫
    var name = “Puss”
}
private var catKey: UInt8 = 0 // 我们还是需要这样的模板
extension Miller {
    var cat: Cat { // cat「实际上」是一个存储属性
        get { 
            return associatedObject(self,key: &catKey) 
                { return Cat() } // 设置变量的初始值
        }
        set { associateObject(self,key: &catKey,value: newvalue) }
    }
}

如果你在家可以跟着练习的话,你可以在 playground 中敲下下面几行代码,来确保它能正常工作。

let grumpy = Miller()
grumpy.cat.name // 显示 Puss
grumpy.cat.name = “Hephaestos”
grumpy.cat.name // 显示 Hephaestos

就这么简单!

致谢:这个实现至少一半来自于 Eric-Paul Lecluse。他在扩展中使用了关联对象,我把这个模式提出来作为一个可重用的类,然后我们一起把这个类修改成了你看到的那两个方法代码是我写的,如果其中有任何错误,都是我的锅。

大佬总结

以上是大佬教程为你收集整理的Swift 扩展「可以」添加存储属性全部内容,希望文章能够帮你解决Swift 扩展「可以」添加存储属性所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。