Property Wrapper для CurrentValueSubject - управление памятью
Я хотел бы создать property wrapper
за CurrentValueSubject
. Я сделал вот так:
@propertyWrapper
public class CurrentValue<Value> {
public var wrappedValue: Value {
get { projectedValue.value }
set { projectedValue.value = newValue }
}
public var projectedValue: CurrentValueSubject<Value, Never>
public init(wrappedValue: Value) {
self.projectedValue = CurrentValueSubject(wrappedValue)
}
}
Это работает, но есть кое-что, что я хотел бы изменить с помощью этого - используйте структуру вместо класса. Проблема с использованием структуры для этого в том, что иногда я мог получитьSimultaneous accesses
ошибка. И я знаю, почему это происходит, когда вsink
от этого издателя я бы попытался прочитать значение из завернутого значения. Так, например, с таким кодом:
@CurrentValue
let test = 1
$test.sink { _ in
print(self.test)
}
И я более-менее знаю почему - потому что когда projectedValue
выполняет свое наблюдение, обернутое значение все еще находится в процессе установки своего значения. В классе это нормально, потому что он просто изменит значение, но со структурой он фактически изменяет саму структуру, поэтому я пытаюсь писать и читать из нее одновременно.
Мой вопрос - есть ли какой-нибудь умный способ преодолеть это, все еще используя структуру? Я не хочуdispatch async
.
Также я знаю, что @Projected
работает аналогично этому propertyWrapper
, но есть большая разница - Projected
выполняется на willSet
, пока CurrentValueSubject
на didSet
. А такжеProjected
в любом случае имеет ту же проблему.
Я знаю, что могу прочитать значение внутри закрытия, но иногда я использую это с различными вызовами функций, которые в конечном итоге могут использовать self.test
вместо.
1 ответ
Попробуйте мою реализацию
@propertyWrapper
class PublishedSubject<T> {
var wrappedValue: T {
didSet {
subject.send(wrappedValue)
}
}
var projectedValue: some Publisher<T, Never> {
subject
}
private lazy var subject = CurrentValueSubject<T, Never>(wrappedValue)
init(wrappedValue: T) {
self.wrappedValue = wrappedValue
}
}