ios - 如何在 Swift 中存储属性,就像在 Objective-C 中一样?

标签 ios swift associated-object

我正在将一个应用程序从 Objective-C 切换到 Swift,我有几个具有存储属性的类别,例如:

@interface UIView (MyCategory)

- (void)alignToView:(UIView *)view
          alignment:(UIViewRelativeAlignment)alignment;
- (UIView *)clone;

@property (strong) PFObject *xo;
@property (nonatomic) BOOL isAnimating;

@end

由于 Swift 扩展不接受像这样的存储属性,我不知道如何保持与 Objc 代码相同的结构。存储属性对我的应用程序非常重要,我相信 Apple 一定已经创建了一些解决方案来在 Swift 中实现这一点。

正如 jou 所说,我正在寻找的实际上是使用关联对象,所以我做了(在另一个上下文中):

import Foundation
import QuartzCore
import ObjectiveC

extension CALayer {
    var shapeLayer: CAShapeLayer? {
        get {
            return objc_getAssociatedObject(self, "shapeLayer") as? CAShapeLayer
        }
        set(newValue) {
            objc_setAssociatedObject(self, "shapeLayer", newValue, UInt(OBJC_ASSOCIATION_RETAIN))
        }
    }

    var initialPath: CGPathRef! {
        get {
            return objc_getAssociatedObject(self, "initialPath") as CGPathRef
        }
        set {
            objc_setAssociatedObject(self, "initialPath", newValue, UInt(OBJC_ASSOCIATION_RETAIN))
        }
    }
}

但是我在执行以下操作时得到了 EXC_BAD_ACCESS:

class UIBubble : UIView {
    required init(coder aDecoder: NSCoder) {
        ...
        self.layer.shapeLayer = CAShapeLayer()
        ...
    }
}

有什么想法吗?

最佳答案

与在 Objective-C 中一样,您不能将存储的属性添加到现有类中。如果你正在扩展一个 Objective-C 类(UIView 绝对是一个),你仍然可以使用 Associated Objects模拟存储的属性:

对于 Swift 1

import ObjectiveC

private var xoAssociationKey: UInt8 = 0

extension UIView {
    var xo: PFObject! {
        get {
            return objc_getAssociatedObject(self, &xoAssociationKey) as? PFObject
        }
        set(newValue) {
            objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN))
        }
    }
}

关联键是一个指针,对于每个关联来说应该是唯一的。为此,我们创建了一个私有(private)全局变量,并将其内存地址用作 & 运算符的键。查看Using Swift with Cocoa and Objective-C 有关如何在 Swift 中处理指针的更多详细信息。

已更新 Swift 2 和 3

import ObjectiveC

private var xoAssociationKey: UInt8 = 0

extension UIView {
    var xo: PFObject! {
        get {
            return objc_getAssociatedObject(self, &xoAssociationKey) as? PFObject
        }
        set(newValue) {
            objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
        }
    }
}

已更新 Swift 4

在 Swift 4 中,它变得更加简单。 Holder 结构将包含我们的计算属性将向世界公开的私有(private)值,从而给人一种存储属性行为的错觉。

Source

extension UIViewController {
    struct Holder {
        static var _myComputedProperty:Bool = false
    }
    var myComputedProperty:Bool {
        get {
            return Holder._myComputedProperty
        }
        set(newValue) {
            Holder._myComputedProperty = newValue
        }
    }
}

关于ios - 如何在 Swift 中存储属性,就像在 Objective-C 中一样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25426780/

相关文章:

ios - 带有白色背景的 UITextView 在仪器和模拟器中显示为颜色混合层

ios - 为什么 Storyboard是空白的并且 View 是灰色的?

ios - @IBAction 只是 Swift 中的一种语法,还是 @Something 在 Swift 中意味着特定的事物?

ios - Swift 3 中的 UICollectionView 在部分中显示其他单元格

ios - 如何使用换行符发推文(通过 Fabric 的 Twitter Rest API)

ios - 在 CoreData 中为每个键保存多个值

ios - 如何在 Xcode 的属性检查器中添加部分名称?

ios - objc_getAssociatedObject返回错误的值

swift - 有没有办法在 Swift 中设置关联对象?

swift - 如何从枚举案例的特定实例中提取关联值?