iOS - How to refresh/update Core Data transient property?
Asked Answered
S

2

5

I'm using a core data, NSFetchedResultsController UITableView, with a transient NSDate attribute. The main reason I have this as a transient property is so my UITableView entries get put into sections based on NSDate, but can move between the sections when the date changes.

So far it seems to work great, but it only updates/refreshes (I'm really new to this, so I don't know if I'm using the correct terminology, sorry!) when I either close the app and kill it from multitasking, or re-run it through Xcode. If I don't do that, the items don't change and aren't put into their correct sections. Is there a way to manually get it to refresh so the user doesn't need to do that to get it to run right?

Thank you!

Swellfish answered 4/8, 2012 at 21:3 Comment(2)
How are the updates propagated? NSFetchedResultsController delegate?Kablesh
It might be relevant that with a SQlite store you cannot use transient attributes for sort descriptors.Commons
L
3

Transient properties are refreshed when you send a refreshObject:mergeChanges: to your object.

The solution provided by Mundi to apply key value observing mechanism might work too and if it does, it is definitely much more convenient than refreshing explicitly.

Lello answered 6/8, 2012 at 6:35 Comment(3)
Hey svena, thanks for the reply. Where would I put the refreshObject:mergeChanges? Would it be inside an action? Thanks!Swellfish
You can refresh the object at the points where you know the date is changed. However, I encourage you to take the approach Mundi recommended. It is much more convenient. It is just good to know that you can always refresh a transient property explicitly as well should you choose to.Lello
It seems that transient properties are not refreshed: "If flag is YES, this method does not affect any transient properties" developer.apple.com/reference/coredata/nsmanagedobjectcontext/…Madea
K
7

First, make sure that you transient property is only used for the sectionNameKeyPath when creating your fetched results controller. Best name it sectionIdentifier (as Apple does in their sample code.) The actual date should be a separate attribute of your entity. (I will call it dateAttribute.

Second, make sure that you specify the key path dependencies in your Entity.m file:

+ (NSSet *)keyPathsForValuesAffectingSectionIdentifier {
    // If the value of dateAttribute changes, the section identifier may change as well.
    return [NSSet setWithObject:@"dateAttribute"];
}

Third, make sure that in your controller, you react appropriately to changes in the managed object context through

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
   if (!self.tableView.editing) [self.tableView reloadData];
   // the quick and dirty method without animations;
   // see referenced code for a more pleasant approach
}

If anything is unclear, take a look at the Apple example DateSectionTitles.

Kablesh answered 5/8, 2012 at 17:2 Comment(5)
Are you 100% sure that the keyPathsForValuesAffecting... forces a refresh while it is a transient property? I have previously noticed that transient properties are refreshed only when refreshObject:mergeChanges: is sent to the object.Lello
So I have it set up almost exactly like the Apple example, but it doesn't seem to refresh when there's a change. The section identifier for each item is created by a big calculation of nsdate differences, but when I launch the app it doesn't seem to calculate those again like it does when I kill the app from multitasking and reopen it.Swellfish
I had to change the Apple code to make it work. If I remember correctly, you have to get rid of the lazy creation of the primitive section identifyer "tmp". Just always execute what is in the if block.Kablesh
Or you could set the transient attribute to nil, when you change the property it depends on. That way, the if block is only executed when the property it depends on changes (see -setTimeStamp: implementation in Event.m in the Apple example DateSectionTitles referred to above).Dric
@Kablesh If you have time, can you please look at this: #24482949Filamentary
L
3

Transient properties are refreshed when you send a refreshObject:mergeChanges: to your object.

The solution provided by Mundi to apply key value observing mechanism might work too and if it does, it is definitely much more convenient than refreshing explicitly.

Lello answered 6/8, 2012 at 6:35 Comment(3)
Hey svena, thanks for the reply. Where would I put the refreshObject:mergeChanges? Would it be inside an action? Thanks!Swellfish
You can refresh the object at the points where you know the date is changed. However, I encourage you to take the approach Mundi recommended. It is much more convenient. It is just good to know that you can always refresh a transient property explicitly as well should you choose to.Lello
It seems that transient properties are not refreshed: "If flag is YES, this method does not affect any transient properties" developer.apple.com/reference/coredata/nsmanagedobjectcontext/…Madea

© 2022 - 2024 — McMap. All rights reserved.