我可以将相关对象添加到Swift Struct吗?

时间:2018-02-22 11:03:49

标签: swift string struct associated-object

我想在Swift String中添加一个额外的属性。我在对象上几次使用这种方法,但似乎它对struct不起作用。虽然,我没有得到任何错误......

这就是我的尝试:

var str = "Hello, StackOverflow"
fileprivate struct AssociatedKeys {
    static var myBool = "myBool"
}

extension String {
    public var myBool: Bool {
        get {
            guard let myBoolObject = objc_getAssociatedObject(self, &AssociatedKeys.myBool) as? NSNumber else {
                return false
            }
            return myBoolObject.boolValue // execution never reaches this line
        }

        set(value) {
            let object = NSNumber(value: value)
            objc_setAssociatedObject(self, &AssociatedKeys.myBool, object, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

str.myBool = true

print(str.myBool)  // prints "false"

打印出它是假的。

起初,我尝试过没有将Bool包装到NSNumber中,但结果是一样的。

甚至可以将关联对象添加到结构体中吗?如果没有,谁能告诉我为什么?

1 个答案:

答案 0 :(得分:0)

基于@Hamish的评论,我创建了以下解决方案来解决此问题。 前提条件:

  • 有一个提出预填充对象的框架,应用程序可以处理这些对象,框架应该知道在以后处理这个对象时修改了哪些属性。

  • 不使用looooong初始化程序来设置MyObject的所有属性是一项设计决定。

在我的示例中,myObject的使用是虚拟的,显示了框架中发生的情况以及应用程序中发生的情况。

// protocol is used, as we could handle more modifiable structs/classes in a common way
protocol PropertyState {
    var isModified: Bool {get set}
}

internal struct ModifiableString : PropertyState {
    var string: String
    var isModified: Bool
}

class MyObject: PropertyState {
    internal var _name = ModifiableString(string: "", isModified: false)
    public var name: String {
        get {
            return _name.string
        }
        set(value) {
            _name.string = value
            _name.isModified = true
        }
    }

    // + N similar properties (they can be other types than String, by implementing other structs, like ModifiableBool)

    var isModified: Bool {
        get {
            return _name.isModified // || _myAnotherProperty.isModified
        }
        set(value) {
            _name.isModified = value
            // _myAnotherProperty.isModified = value
        }
    }
}

// internal filling of the object inside of the framework
let myObject = MyObject()
myObject.name = "originalValue"
print(myObject.isModified)   // true
// filling the object with values ended, so we can set the state
myObject.isModified = false
print(myObject.isModified)   // false

// the app can work with the object
// let myObject = Framework.getObject()
myObject.name = "modifiedValue"

// now the framework should now which properties are modified
print(myObject._name.isModified)   // true