31

I have a var declared in a class like so:

@NSManaged var isFavorite: Bool

I would like to declare a property observer, very similar to the one below.

 var organization: String {
        didSet { postNotificationWithName( "newData" ) }
    }

However, Swift tells me that having property observers on NSManaged vars is not allowed. Is there any way I can implement such a feature or something similar for my isFavorite variable?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Satre
  • 1,724
  • 2
  • 18
  • 22
  • Do you want to post a notification or support key-value observers, or both? Where does `postNotificationWithName()` come from? – Jon Shier May 13 '15 at 02:27

3 Answers3

38

Yes-- delete the @NSManaged. It's not absolutely required, but if you delete it you unfortunately need to implement get and set for the property. You would need to add something like

The @objc is only needed if you want to be able to do KVO on the property.

@objc public var newData: String? {
    set {
        willChangeValue(forKey: "newData")
        setPrimitiveValue(newValue, forKey: "newData")
        didChangeValue(forKey: "newData")
    }
    get {
        willAccessValue(forKey: "newData")
        let text = primitiveValue(forKey: "newData") as? String
        didAccessValue(forKey: "newData")
        return text
    }
}

It's kind of annoying to implement both of these if you don't actually need them but that's the way it is for now.

Since you'll have a set, you might not need a didSet, but you can still add a didSet if you want one.

Marc Etcheverry
  • 1,010
  • 1
  • 10
  • 15
Tom Harrington
  • 69,312
  • 10
  • 146
  • 170
  • 2
    The reason I have declared the variable as `NSManaged` is that I require that variable to be cached locally using the Core Data (as a part of Parse's local data store). Is there a way to resolve that? – Satre May 14 '15 at 05:36
  • 4
    Using `@NSManaged` is not necessary when using Core Data if you implement accessors like those in the answer. The code above still saves data to the persistent store. – Tom Harrington May 14 '15 at 15:12
  • Xcode gives me an error that my `Attendee` class doesn't have the members named `setPrimitiveValue` and `didAccessValueForKey`. – Satre May 17 '15 at 18:56
  • Every class that subclasses `NSManagedObject` implements `setPrimitiveValue(_:,key:)` and `didAccessValueForKey(_:)`. If you're getting those errors then either you're not subclassing `NSManagedObject` or you got the method signature wrong. – Tom Harrington May 18 '15 at 02:59
  • Hey, thanks for the solution. But the problem is that sometimes it doesn't set the value – M090009 Sep 27 '16 at 19:40
  • 1
    @M090009 If not then there's something wrong with your implementation. You should ask a new question that presents your code in detail. – Tom Harrington Sep 27 '16 at 20:38
  • Make sure to mark the property with @objc if you want to still be able to do KVO on it. – Marc Etcheverry Nov 09 '19 at 00:55
  • Usually, `@NSManaged var isFavorite: Bool` is placed in an extension. If we remove `@NSManaged`, we will get error "Extensions must not contain stored properties". May I know how can we deal with such? – Cheok Yan Cheng Oct 12 '21 at 16:39
  • @CheokYanCheng You deal with it by making it a computed property, using a `get` and `set` block as shown in the answer above. – Tom Harrington Oct 12 '21 at 17:04
  • Thanks. I think I get what you mean. But, is there any documentation from Apple which describes such technique. I can find API doc for every individual functions. But, i cant find a documents which integrates all the functions together… – Cheok Yan Cheng Oct 12 '21 at 19:34
4

Whoops! Paul Patterson is right. What you're supposed to use is Key Value Observing - which is exactly what it says you're supposed to do in the link I suggested.

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html

See also swift notes: https://developer.apple.com/library/mac/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html (use the 'On This Page' menu at the top right of the page for Key-Value Observing)

So something like

objectToObserve.addObserver(self, forKeyPath: "organization", options: .New, context: &myContext)

paired with

override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
kwerle
  • 2,225
  • 22
  • 25
-2

Override NSManagedObject's func didChangeValue(forKey key: String) see (https://developer.apple.com/documentation/coredata/nsmanagedobject/1506976-didchangevalue)

Wizard of Kneup
  • 1,863
  • 1
  • 18
  • 35