I am using this code in a SwiftUI view model:
car.publisher(for: \.sold, options: [.new])
.removeDuplicates()
.receive(on: RunLoop.main)
.sink { [weak self] sold in
guard let self = self else { return }
.... here is reference the car entity for some logic ....
}
.store(in: &subscribers)
All works fine, until I actually delete that Car entity and the sink kicks in and then .... here is reference the car entity for some logic ....
runs and it crashes trying to use a DELETED Core Data entity.
My pattern seems to be wrong here. Is there a way for that sink to cancel automatically when that car entity is deleted from context?
CodePudding user response:
You can use faultingState
to track this scenario. From documentation:
0
if the object is fully initialized as a managed object and not transitioning to or from another state, otherwise some other value. This property allows you to determine if an object is in a transitional phase when receiving a key-value observing change notification.
So you can ignore this event like this:
.sink { [weak self] sold in
guard let self = self, car.faultingState == 0 else { return }
//
}
If you wanna actually cancel this sink, you can store cancellables inside the object so you can cancel them during prepareForDeletion
.
To do this you need to change object code generation, more info can be found here. Change to Category/Extension - in this case you can create a class and override prepareForDeletion
, and Xcode will still generate all the properties for you.
Now you can move all publisher logic into your class:
@objc(Car)
public class Car: NSManagedObject {
private var subscribers = Set<AnyCancellable>()
func observe<Value: Equatable>(keyPath: KeyPath<Item, Value>, receiveValue: @escaping ((Value) -> Void)) {
publisher(for: keyPath, options: [.new])
.removeDuplicates()
.receive(on: RunLoop.main)
.sink(receiveValue: receiveValue)
.store(in: &subscribers)
}
public override func prepareForDeletion() {
super.prepareForDeletion()
subscribers.removeAll()
}
}
Or just use it to store cancellables.