Swift: Reflecting Properties of Subclass of Nsmanagedobject

How to reflect not managed properties of NSManagedObject

When you get the list of properties using class_copyPropertyList, you can iterate through the list to look at each property in turn:

var propertyCount : UInt32 = 0
let properties = class_copyPropertyList(Account.self, &propertyCount)

for var i=0; i<Int(propertyCount); i++ {
let property = properties[i]
let propertyName = String(UTF8String: property_getName(property))
....
}

The type of each property is contained in one of the property attributes, as a string:

    let propertyType = property_copyAttributeValue(property, "T")
let propertyTypeString = String(UTF8String: propertyType)

For your lastOperation property the string will look something like @\"Operation\". You'll have to clean up that string a little to get Operation.

I wrote a blog post a while ago describing something similar to what you're trying to do. The code is in Objective-C but all the functions, methods, etc are the same.

Is it possible to override getters and setters for @dynamic properties in an NSManagedObject subclass?

Never call [super valueForKey:..] in a NSManagedObject subclass! (unless you implemented them in a superclass yourself)
Instead use the primitive accessor methods.

Sample getter/setter implementation from ADC:

@interface Department : NSManagedObject
@property(nonatomic, strong) NSString *name;
@end

@interface Department (PrimitiveAccessors)
- (NSString *)primitiveName;
- (void)setPrimitiveName:(NSString *)newName;
@end

@implementation Department

@dynamic name;

- (NSString *)name
{
[self willAccessValueForKey:@"name"];
NSString *myName = [self primitiveName];
[self didAccessValueForKey:@"name"];
return myName;
}

- (void)setName:(NSString *)newName
{
[self willChangeValueForKey:@"name"];
[self setPrimitiveName:newName];
[self didChangeValueForKey:@"name"];
}

@end

NSManagedObject changes reflect changed on the fly

Solution:

var yourObject: YourManagedObjectClass! // here your example object

override func viewDidLoad() {
// … your other init code
// don't forget to remove observer

NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(self.objectContextObjectsDidChange(_:)), name: NSManagedObjectContextObjectsDidChangeNotification, object: yourObject.managedObjectContext)
}

/// Object did changed, let's look what had changed
func objectContextObjectsDidChange(notification: NSNotification) {
guard let userInfo = notification.userInfo,
let updatedObjects = userInfo[NSUpdatedObjectsKey] as? Set<NSManagedObject> where updatedObjects.count > 0 else { return }

for object in updatedObjects {
if let updatedObject = object as? YourManagedObjectClass where updatedObject.objectID == yourObject.objectID {
// Data changed in our object, you can refresh your label here
// Don't forget about threads if your object wasn't in main context

label.text = updatedObject.text
return
}
}
}

Swift Core Data - Error accessing fetched entity with NSManagedObject Subclass

Wow I feel so dumb.
It seems the problem was the way I was calling the 'fetchShows()' method.
I needed to actually create and allocate a 'CoreDataManager' object and call the method using that object, instead of trying to just make a call to the class method:

let DataManager = CoreDataManager()
self.shows = DataManager.fetchShows()

And now it works!

Calculated Properties based on properties of underlying Entities in Core Data

In Swift 4 add the attributes @objc and dynamic to make the computed property key-value coding compliant.

@objc dynamic var totalSwimSeconds: Int64 { ...

Edit:

To observe the workouts property override keyPathsForValuesAffectingValue in Day

override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
switch key {
case "totalSwimSeconds": return Set(["workouts"])
default: return super.keyPathsForValuesAffectingValue(forKey:key)
}
}

Get properties of NSManagedObject as NSDictionary

There is a faster way to convert an NSManagedObject to an NSDictionary (from Matthias Bauch response at https://stackoverflow.com/a/5664745/2294824) :

NSArray *keys = [[[myObject entity] attributesByName] allKeys];
NSDictionary *dict = [myObject dictionaryWithValuesForKeys:keys];

Detecting changes to a specific attribute of NSManagedObject

This type of circumstance is where you need a custom NSManagedObject subclass. You need the subclass because you are adding a behavior, reacting to a price change, to the managed object.

In this case, you would override the accessor for the price attribute. Create a custom subclass using the popup menu in the data model editor. Then select the price attribute and choose 'Copy Obj-C 2.0 Implementation to the Clipboard`. It will give you a lot of stuff but the key bit will look like this:

- (void)setPrice:(NSNumber *)value 
{
[self willChangeValueForKey:@"price"];
[self setPrimitivePrice:value];
[self didChangeValueForKey:@"price"];
}

Just add the code to deal with the price change and you are done. Anytime a specific product's price changes, the code will run.



Related Topics



Leave a reply



Submit