I have a theoretical issue here. I've learnt that DbContextConfiguration.AutoDetectChangesEnabled property value determines whether the automatic detection of changes in the context is enabled. But, I've set it to false and the context still persists changes even when I don't call DbChangeTracker.DetectChanges manually.
Note: the only case when it doesn't persist is when I make changes to ICollection property of an entity (but it still persists when I change a navigation property i.e.: myEntity.OtherEntity = myOtherEntity).
So, I'd like to know what I've learnt wrong :)
Thanks a lot.
Giorgi
It happened because I manually set entity's state to Modified. This made the context save the changes for primitive and navigation properties but apparently wasn't enough for updating the collection property. Problem is solved.
Related
I have a core data entity named Film which has properties title and date. I noticed that the generated NSManagedObject subclass contains optional NSManaged properties even though I marked the properties as non optional in the core data inspector.
Can I can manually change it as non-optional property or is it a better choice to leave it as optional? Why?
"Optional" means something different to Core Data than it does to Swift.
If a Core Data attribute is not optional, it must have a non-nil value when you save changes. At other times Core Data doesn't care if the attribute is nil.
If a Swift property is not optional, it must have a non-nil value at all times after initialization is complete.
Making a Core Data attribute non-optional does not imply that it's non-optional in the Swift sense of the term. That's why generated code makes these properties optional-- as far as Core Data is concerned, it's legal to have nil values except when saving changes.
Update: After writing this answer I wrote a deep dive blog post explaining things in more detail: https://www.atomicbird.com/blog/clash-of-the-optionals/
This is a known issue. Some people change it to non-optional with no adverse effects, I keep it the way it was generated and hope for early fix.
It always helps if you submit a bug to Apple to increase visibility and priority.
Create managedobject class and change the entity class type to manual and add these classes to your project scope.
Edit your managedObject to make them non-optional. This means you need to maintain this class yourself and do any changes both in the core data model and the class
If your data model is stable and won't be changed then you can use this.
The Optional checkbox in the data model inspector has nothing to do with Swift optionals. The checkbox determines whether or not the attribute is required to have a value.
If you deselect the Optional checkbox for an attribute, you must give that attribute a value or you will get an error when saving. By selecting the Optional checkbox you can save without giving the attribute a value. Suppose you have a description attribute that's a string. If you select the Optional checkbox you could leave the description blank and still save the entity.
Here's another example. Suppose you have text fields to let a person enter their home, work, and cell phone numbers. These phone numbers should be optional attributes. You wouldn't want to require someone to have a home phone number, a work phone number, and a cell phone number just to save the person's data.
I discovered that when setting a parent true, that parent's children are all called 'OnEnable' function. Even though children are all set true already.
I don't want to call 'OnEnable' function even though it's already set true.
How can I prevent it?
This documentation on execution order may be useful to you.
If you have logic in the child objects that you do not want to call from the parent being set as active, than remove it from OnEnable and hook it up to your own delegate somewhere else.
You are going to have the same thing happen with the Start and Awake functions as well. Personally I would try and find a way to abstract your code a bit more to make sure the child object is not dependent on the parent.
SetActive() behavior is inherited by all of the children of that particular gameObject. In order to solve your problem you most likely have to restructure your GameObject hierarchy.
I have a strange problem here. I am not getting the callbacks for "Update" operations on my NSManagedObject, but where as any objects inserted into or removed from the collection of that entity type would trigger the delegate callbacks.
Before I proceed with the question further, I would like to inform about my setup:
NSFetchedResultsController is properly configured. Made sure that
the property which is being modified externally is not any of the
sort keys for the fetchedResultsController as required by this Apple
documentation:
An update is reported when an object’s state changes, but the changed
attributes aren’t part of the sort keys.
There is only single managed object context in which these modifications are happening.
Since insert and delete operations are being reported to the
delegate, I presume there is something fishy about the Update
operations
I was drilling down the Restkit code with help of RKLogs to see where exactly the mapping happens and where the coredata object is being updated to find out the reason why am not getting the update delegate callbacks.
In the class RKManagedObjectMappingOperation -performMapping method, Mr. Blake Watters has documented the reason why MOC callbacks are not triggered upon updates:
- (BOOL)performMapping:(NSError **)error
{
BOOL success = [super performMapping:error];
if ([self.objectMapping isKindOfClass:[RKManagedObjectMapping class]]) {
/**
NOTE: Processing the pending changes here ensures that the managed object context generates observable
callbacks that are important for maintaining any sort of cache that is consistent within a single
object mapping operation. As the MOC is only saved when the aggregate operation is processed, we must
manually invoke processPendingChanges to prevent recreating objects with the same primary key.
See https://github.com/RestKit/RestKit/issues/661
*/
[self connectRelationships];
}
return success;
}
But I cannot for the life of myself figure out how to fix this? Coz it was done purposefully?
Has anyone faced same problem? How do I fix it?
Thanks,
Raj Pawan
There was 1 mistake from my part and 1 other thing (Ignorance) which I was not aware of and due to which I faced this problem:
Mistake:
Despite many discussion all over the forums, I was wrong to state my second listed item:
There is only single managed object context in which these
modifications are happening.
I had wrongly logged and found out that I was in the same context! So dumb of me!
Ignorance:
I did some digging through the RK code thinking something fishy is going on there, checked Blake Watters' comments and his commit 4b394f8c1e1f to see if the earlier code there (call to -processPendingChanges) which is now removed was causing any issue and not letting the delegate to be informed about updates.
Found out that this was indeed on a separate thread and yes it had its own MOC which I had missed out. Next thing to do was simple, I implemented the mechanism to merge changes of a MOC from different thread into main MOC. But this did not work either!
The reason turns out that I am in a very initial stages of the development of application. I am just mapping the json response with coredata objects using RestKit and I am nowhere utilising it! I was just logging the coredata objects in GDB and they remained in their fault state always! I was relying upon the -objectLoader callbacks and the NSNotification object to see that there was indeed an Update available. At some point while testing I happened to log a property of the managed object which is changed in the Notification callback before it was merged back to the main MOC. This faulted the managed object and loaded all properties of the managed object. Now when the secondary thread MOC changes were merged with the main thread MOC, my NSFetchedResultsControllerDelegate callbacks started triggering.
I have a CoreData model in my iPhone app, which is linked to a SQL Database with more than 50k records. When I generate the records classes, Xcode uses the #dynamic directive for properties. I have a property named "ISFAV", NSNumber type (CoreData does not use BOOL or Integer, it uses object types). Being short, I change the ISFAV property when the user taps on a button in this way:
if (![record.ISFAV intValue])
record.ISFAV=[NSNumber numberWithInt:1];
else
record.ISFAV=[NSNumber numberWithInt:0];
Quite simple. But if I try to tap many times on the same button sequentially, the iPhone takes too much time (the button remains in the hold state for a time that increase progressively). This happens even if I change record, adding\removing many records from favorites sequentially (instead of adding\deleting the same record from favorites).
If I change the original accessor method to #synthesize, the problem seems to be solved.
Is it correct to use the synthesize directive for accessor methods in CoreData?
Thank you very much!
#edit
Using the synthesize directive, no changes are made to the CoreData model when I save the context :-\ The problem is still unsolved :-\
#dynamic is a flag that just tells the compiler that the method will exist at run time and to not warn about it now. You should not be using #synthesize with Core Data properties.
How do you know your hotspot is with setting the Core Data property? Have you profiled the code? In my experience, changing one attribute in Core Data is not going to be slow, it will be 1/1000th of a second or faster. Are you saving to disk each time you change that one property? Are you doing something else in the call?
I would profile the code first and find out where the hotspot really is. Use Instruments and confirm.
I have a UITabBarController that I would like to assign to another object, so that that object can control it:
watchListView.tabBarController = self.stTabBarController;
During this assignment the value of both self.stTabBarController and watchListView.tabBarController are 0x0.
How can I assign the UITabBarController's?
The assignment is (at least syntactically) correct. The problem is that you're doing at a time when the source property has itself not been set.
Without knowing more about when and where this is happening it's difficult to guess what the problem is. At what point are you trying to make this call? Does the controller ever exist? Is there some subsequent time where the property is demonstrably non-nil?