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
Nssortdescriptor Sorting Using Nsdate in Swift
Toggle Sidebar in Swiftui Navigationview on MACos
How to Get Part of a String in Swift
Using Decodable with Inheritance Raises an Exception
Uitableviewautomaticdimension Not Working on iOS 8
How to Disable "Save to Files" in iOS 11
Rotating Uitextview Programmatically
How to Set Alignment for Wkinterface Label Using Setattributedtext
How to Add a Move Back to User Location Button in Swiftui
"Raw Value for Enum Case Is Not Unique" for Swift Enum with Float Raw Values
How to Get Mouse Location with Swiftui
How to Use Nsvisualeffectview to Blend Window with Background
Rotate a Text View and Its Frame in Swiftui
How to Read File Data Applications Document Directory in Swift
Swift - How to Resize a Uiview Based on Its Uilabel Size (That Is Inside)