propertyWrapper下标未调用。为什么?
我正在实现自己的atomicdictionary
属性包装器如下:
@propertyWrapper
public class AtomicDictionary<Key: Hashable, Value>: CustomDebugStringConvertible {
public var wrappedValue = [Key: Value]()
private let queue = DispatchQueue(label: "atomicDictionary.\(UUID().uuidString)",
attributes: .concurrent)
public init() {}
public subscript(key: Key) -> Value? {
get {
queue.sync {
wrappedValue[key]
}
}
set {
queue.async(flags: .barrier) { [weak self] in
self?.wrappedValue[key] = newValue
}
}
}
public var debugDescription: String {
return wrappedValue.debugDescription
}
}
现在,当我使用它的使用如下:
class ViewController: UIViewController {
@AtomicDictionary var a: [String: Int]
override func viewDidLoad() {
super.viewDidLoad()
self.a["key"] = 5
}
}
atomicdicationary
的订阅函数未调用!
有人对为什么这样做有任何解释吗?
I am implementing my own AtomicDictionary
property wrapper as follows:
@propertyWrapper
public class AtomicDictionary<Key: Hashable, Value>: CustomDebugStringConvertible {
public var wrappedValue = [Key: Value]()
private let queue = DispatchQueue(label: "atomicDictionary.\(UUID().uuidString)",
attributes: .concurrent)
public init() {}
public subscript(key: Key) -> Value? {
get {
queue.sync {
wrappedValue[key]
}
}
set {
queue.async(flags: .barrier) { [weak self] in
self?.wrappedValue[key] = newValue
}
}
}
public var debugDescription: String {
return wrappedValue.debugDescription
}
}
now, when I use it as follows:
class ViewController: UIViewController {
@AtomicDictionary var a: [String: Int]
override func viewDidLoad() {
super.viewDidLoad()
self.a["key"] = 5
}
}
The subscript function of the AtomicDicationary
is not called!!
Does anybody have any explanation as to why that is?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
属性包装器 仅提供基本访问者方法,基本访问者方法,但就是这样。它不会拦截下标或其他方法。
原始属性包装纸提案向我们展示了幕后发生的事情。它考虑了一个假设的属性包装器,
懒惰
,其中:请注意,
foo
只是int
计算属性。_foo
是Lazy&lt; int&gt;
。因此,在您的
A [“ KEY”] = 5
示例中,它不会使用您的属性包装器的下标操作员。它将获取
与a
关联的值,使用字典自己的下标操作员更新该值(而不是属性包装器的下标运算符),然后将设置
与a
关联的值。这就是所有属性包装器所做的,提供
get
和set
配件。例如,声明:转换为:
您定义的任何其他方法仅通过
_a
在本示例中访问,而不是a
(这只是一个计算属性BrappedValue
_a
)。因此,最好只是为“原子词典”定义适当的类型:
这
为您提供了想要的行为。
而且,如果您要提供
CustomDebugStringConvertible
一致性,请确保在此处使用您的同步机制:所有与包装值的交互都必须同步。
显然,您可以将此通用模式与所需的任何同步机制一起使用,例如上述阅读器撰写的模式,GCD串行队列,锁,演员等(读取器撰写的模式具有自然吸引力,但实际上,在那里, 的机制。
通常是更好 人们应该始终对通用线程安全集合保持警惕,因为我们代码的正确性依赖于更高级别的同步。
Property wrappers merely provide an interface for the basic accessor methods, but that’s it. It’s not going to intercept subscripts or other methods.
The original property wrapper proposal SE-0258 shows us what is going on behind the scenes. It contemplates a hypothetical property wrapper,
Lazy
, in which:Note that
foo
is just anInt
computed property. The_foo
is theLazy<Int>
.So, in your
a["key"] = 5
example, it will not use your property wrapper’s subscript operator. It willget
the value associated witha
, use the dictionary’s own subscript operator to update that value (not the property wrapper’s subscript operator), and then it willset
the value associated witha
.That’s all the property wrapper is doing, providing the
get
andset
accessors. E.g., the declaration:translates to:
Any other methods you define are only accessible through
_a
in this example, nota
(which is just a computed property that gets and sets thewrappedValue
of_a
).So, you’re better off just defining a proper type for your “atomic dictionary”:
And
That gives you the behavior you want.
And if you are going to supply
CustomDebugStringConvertible
conformance, make sure to use your synchronization mechanism there, too:All interaction with the wrapped value must be synchronized.
Obviously you can use this general pattern with whatever synchronization mechanism you want, e.g., the above reader-writer pattern, GCD serial queue, locks, actors, etc. (The reader-writer pattern has a natural appeal, but, in practice, there are generally better mechanisms.)
Needless to say, the above presumes that subscript-level atomicity is sufficient. One should always be wary about general purpose thread-safe collections as often the correctness of our code relies on a higher-level of synchronization.