我可以将关联对象添加到 Swift 结构吗?
Can I add associated object to Swift Struct?
我想在 Swift 字符串中添加一个额外的 属性。我在对象上使用过几次这种方法,但它似乎不适用于结构。虽然,我没有收到任何错误...
这是我试过的:
var str = "Hello, Whosebug"
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,结果还是一样
甚至可以将关联对象添加到结构中吗?如果没有,谁能告诉我为什么?
根据@Hamish 的评论,我创建了以下解决方案来解决该问题。
先决条件:
有一个建议预填充对象的框架,应用程序在这些对象上工作,框架应该知道在稍后处理这个对象的过程中修改了哪些属性。
不使用太长的初始值设定项来设置 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
我想在 Swift 字符串中添加一个额外的 属性。我在对象上使用过几次这种方法,但它似乎不适用于结构。虽然,我没有收到任何错误...
这是我试过的:
var str = "Hello, Whosebug"
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,结果还是一样
甚至可以将关联对象添加到结构中吗?如果没有,谁能告诉我为什么?
根据@Hamish 的评论,我创建了以下解决方案来解决该问题。 先决条件:
有一个建议预填充对象的框架,应用程序在这些对象上工作,框架应该知道在稍后处理这个对象的过程中修改了哪些属性。
不使用太长的初始值设定项来设置
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