deleteObject hangs my app - ios

TTNetworkDataSource* netSource = [TTNetworkDataSource sharedSource];
[netSource setContext:self];
TTDataSourceResponse* districtsResponse = [netSource requestDataWithQuery:#{#(OBJECT_TYPE): [HotlineDistrict clsName]}];
if (districtsResponse != nil) {
NSArray* objects = [self executeFetchRequestUnsafe:[NSFetchRequest fetchRequestWithEntityName:[HotlineDistrict clsName]] error:&localError];
NSInteger i = 0;
if (localError != nil) {
result = NO; return;
} else {
NSLog(#"%lu = fetchedObjects, %lu = districtsResponse", (unsigned long)objects.count, (unsigned long)districtsResponse.objects.count);
for (NSManagedObject* obj in objects) {
NSLog(#"Deleted Objects in fetched objects %ld", (unsigned long)i++);
[self deleteObject:obj];
}
for (NSManagedObject* obj in districtsResponse.objects) {
NSLog(#"Inserted Object in districtsResponse %ld", (unsigned long)i++);
[self insertObject:obj];
}
}
} else {
localError = [NSError errorInfo:#{NSLocalizedDescriptionKey: #"Error when getting districts."}];
result = NO;
}
TTDataSourceResponse* requestTypeResponse = [netSource requestDataWithQuery:#{#(OBJECT_TYPE): [HotlineRequestType clsName]}];
if (requestTypeResponse != nil) {
NSArray* objects = [self executeFetchRequestUnsafe:[NSFetchRequest fetchRequestWithEntityName:[HotlineRequestType clsName]] error:&localError];
NSInteger j = 0;
if (localError != nil) {
result = NO; return;
} else {
NSLog(#"%lu = fetchedObjects, %lu = requestTypeResponse", (unsigned long)objects.count, (unsigned long)requestTypeResponse.objects.count);
for (NSManagedObject* obj in objects) {
NSLog(#"Deleted Objects in fetched objects %ld", (unsigned long)j++);
[self deleteObject:obj];
}
for (NSManagedObject* obj in requestTypeResponse.objects) {
NSLog(#"Deleted Objects in requestTypeResponse %ld", (unsigned long)j++);
[self insertObject:obj];
}
}
} else {
localError = [NSError errorInfo:#{NSLocalizedDescriptionKey: #"Error when getting request types."}];
result = NO;
}
Here's my code, after [self deleteObject:obj] my app hangs
Manual debug by:
NSLog(#"%lu = fetchedObjects, %lu = districtsResponse", (unsigned long)objects.count, (unsigned long)districtsResponse.objects.count);
Give this result:
802 = fetchedObjects, 47 = districtsResponse
NSLogs in loops give enumeration of objects, in total we have summ of fetchedObjects and districtsResponse, even if place NSLog in the end of loop body. So its says that loop finished well. But the app is hangs. Those loops 2, it don't touch second loop, and if we delete those loops with deleteObject - it works.

You must not subclass NSManagedObjectContext as Apple says:
https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObjectContext_Class/index.html
Subclassing Notes
You are strongly discouraged from subclassing NSManagedObjectContext. The change tracking and undo management mechanisms are highly optimized and hence intricate and delicate. Interposing your own additional logic that might impact processPendingChanges can have unforeseen consequences. In situations such as store migration, Core Data will create instances of NSManagedObjectContext for its own use. Under these circumstances, you cannot rely on any features of your custom subclass. Any NSManagedObject subclass must always be fully compatible with NSManagedObjectContext (that is, it cannot rely on features of a subclass of NSManagedObjectContext).

I found the answer, our api sended nil values to the required attribute in entity, but anyway, thanks a lot guys

Related

iOS fetching data from server inside for loop

I want to fetch data from server with multiple calls inside for loop. I'm passing different parameter each time. I know it is possible to fetch data like, I'm fetching in code below :
for (NSDictionary *feedItem in [feed objectForKey:#"content"]) {
// url with feedItem data.
NSURL *url = ....
[UrlMethod GetURL:url success:^(NSDictionary *placeData) {
if (placeData) {
dispatch_async(dispatch_get_main_queue(), ^{
// adding object to table data source array
[dataSourceArray addObject:[placeData objectForKey:#"data"]];
// reloading table view.
[self.tableView reloadData];
});
}
} failure:^(NSError *error) {
}];
}
The problem is, Whenever I add data to dataSourceArry, It is not adding sequentially. It is adding according to response of API calls. Please let me know, If it is not clear.
In your case, I would allocate a mutable array first and set [NSNull null] at each position:
NSInteger count = [[feed objectForKey:#"content"] count];
NSMutableArray *dataSourceArray = [NSMutableArray arrayWithCapacity:count];
for (NSInteger i = 0; i < count; ++i) {
[dataSourceArray addObject:[NSNull null]];
}
Then, I would use something called dispatch groups (see more here http://commandshift.co.uk/blog/2014/03/19/using-dispatch-groups-to-wait-for-multiple-web-services/):
__block NSError *apiCallError = nil; // Just to keep track if there was at least one API call error
NSInteger index = 0;
// Create the dispatch group
dispatch_group_t serviceGroup = dispatch_group_create();
for (NSDictionary *feedItem in [feed objectForKey:#"content"]) {
// Start a new service call
dispatch_group_enter(serviceGroup);
// url with feedItem data.
NSURL *url = ...
[UrlMethod GetURL:url success:^(NSDictionary *placeData) {
if (placeData) {
dispatch_async(dispatch_get_main_queue(), ^{
// Add data to Data Source
// index should be the correct one, as the completion block will contain a snapshot of the corresponding value of index
dataSourceArray[index] = [placeData objectForKey:#"data"];
}
dispatch_group_leave(serviceGroup);
} failure:^(NSError *error) {
apiCallError = error;
dispatch_group_leave(serviceGroup);
}];
index++;
}
dispatch_group_notify(serviceGroup, dispatch_get_main_queue(),^{
if (apiCallError) {
// Make sure the Data Source contains no [NSNull null] anymore
[dataSourceArray removeObjectIdenticalTo:[NSNull null]];
}
// Reload Table View
[self.tableView reloadData];
});
Hope it works for you.
This might be of help for you,
//keep dictionary property which will store responses
NSMutableDictionary *storeResponses = [[NSMutableDictionary alloc]init];
//Somewhere outside function keep count or for loop
NSInteger count = 0;
for (NSDictionary *feedItem in [feed objectForKey:#"content"]) {
//Find out index of feddItem
NSInteger indexOfFeedItem = [[feed objectForKey:#"content"] indexOfObject:feedItem];
NSString *keyToStoreResponse = [NSString stringWithFormat:#"%d",indexOfFeedItem];
// url with feedItem data.
NSURL *url = ....
[UrlMethod GetURL:url success:^(NSDictionary *placeData) {
if (placeData) {
//instead of storing directly to array like below
// adding object to table data source array
[dataSourceArray addObject:[placeData objectForKey:#"data"]];
//follow this
//increase count
count++;
[storeResponses setObject:[placeData objectForKey:#"data"] forKey:keyToStoreResponse];
// reloading table view.
if(count == [feed objectForKey:#"content"].count)
{
NSMutableArray *keys = [[storeResponses allKeys] mutableCopy]; //or AllKeys
//sort this array using sort descriptor
//after sorting "keys"
for (NSString *key in keys)
{
//add them serially
[dataSourceArray addObject:[storeResponses objectForKey:key]];
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
}
} failure:^(NSError *error) {
}];
}
Edit : The answer I have given is directly written here,you might face compilation errors while actually running this code
Don't reload your table each time in the loop. After the loop finishes fetching data , do a sorting on your datasourcearray to get the desired result and then reload table.
This is because you're calling web-services asynchronously so it's not give guarantee that it's give response in sequence as you have made request!
Now solutions for that :
You should write your api like it's give all data at a time. So,
You not need to make many network call and it will improve
performance also!
Second thing you can make recursive kind of function, I mean make another request from completion handler of previous one. In this case once you got response then only another request will be initialize but in this case you will have to compromise with performance!! So first solution is better according to me!
Another thing you can sort your array after you get all the responses and then you can reload your tableView
Try the following :-
for (NSDictionary *feedItem in [feed objectForKey:#"content"]) {
// url with feedItem data.
NSURL *url = ....
[UrlMethod GetURL:url success:^(NSDictionary *placeData) {
if (placeData) {
// adding object to table data source array
[dataSourceArray addObject:[placeData objectForKey:#"data"]];
// reloading table view.
dispatch_sync(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
} failure:^(NSError *error) {
}];
}

CoreData NSSet-Like behavior for NSManagedObjects with the same values

I have a Chat-App with a Data-Modell like this.
User <--> Conversation <-->> Message
My Problem now: Sometimes, if I get old messages from a Backup, I have Messages twice in my DataModel. I'd like to have a NSSet-Like Class which recognizes, if a Message-Object has exactly the same values on it's properties. I've read, that I must not override the methods -hash and -isEqual:, so I don't know how to do it. Any Idea? Here is some code...
+(void)addMessages:(NSSet<JSQMessage *> *)messages toConversation:(Conversation *)conversation
{
DataManager * dataManager = [DataManager dataManager];
NSMutableSet * storeSet = [NSMutableSet setWithCapacity:messages.count];
for (JSQMessage * jsqMessage in messages) {
Message * message = [NSEntityDescription insertNewObjectForEntityForName:CDEntityNameMessage inManagedObjectContext:[dataManager managedObjectContext]];
message.senderId = jsqMessage.senderId;
message.senderDisplayName = jsqMessage.senderDisplayName;
message.text = jsqMessage.text;
message.date = jsqMessage.date;
[storeSet addObject:message];
}
[conversation addMessages:storeSet];
NSError *error;
if (![[dataManager managedObjectContext] save:&error]) {
NSLog(#"Something went wrong: %#", [error localizedDescription]);
} else {
//Saved successfull
}
}
And the Conversation -addMessages: Method is the one automatically generated from Xcode/CoreData
- (void)addMessages:(NSSet<Message *> *)values;
One way of doing it would be to add unique constraints on your entity for one or more attributes. But, this feature was added from iOS 9. Here's the link to the WWDC video explaining it:
https://developer.apple.com/videos/play/wwdc2015/220/
As a final option, you can always override hash and equal, if that suits your logic and requirements.
You hash method could look something like this:
- (NSUInteger)hash
{
NSInteger hashResult = 0;
for (NSObject *ob in self)
{
hashResult ^= [ob hash];
}
}
This is not the best implementation of a hash function. Check out this answer: https://stackoverflow.com/a/5915445/2696922
For the isEqual method, it could look something like:
- (BOOL)isEqual:(id)object
{
if (self == object)
{
return YES;
}
if (object == nil || ![object isKindOfClass:[JSQMessage class]])
{
return NO;
}
JSQMessage *jsqMessage = (JSQMessage*)object;
//You can have more parameters here based on your business logic
if (self.message != jsqMessage.message && self.date != jsqMessage.date)
{
return NO;
}
}
What I do now is checking manually, if there is a Object with same Attributes in my MOC. If there is one, I skip the creation. I know, it is a bit inefficient but with my expected number of messages, this should be no problem.
NSFetchRequest * fr = [NSFetchRequest fetchRequestWithEntityName:CDEntityNameMessage];
[fr setPredicate:[NSPredicate predicateWithFormat:#"text == %# AND date == %# AND conversation.user.objectId == %#", message.text, message.date, chatpartner.objectId]];
NSArray * results = [[self managedObjectContext] executeFetchRequest:fr error:nil];
if (results && results.count > 0) {
continue;
}

Error dealing with saveWithBlock and relation in MagicalRecord

I'm using MagicalRecord to change my custom CoreData functions with something better.
I have two entities: Offer (videogame offers) and System (consoles, PC, etx). An Offer can have one or many Systems, and I get all the data from a Parse query, where I save all my data.
I only have 8 Systems so when my app starts, I fetch all of them and save with Magical Record. Then I call my method to fetch some offers and transform the PFObjects from Parse into entities.
This is how
+ (void)createOrUpdateOffersWithArray:(NSArray *)objects completion:(void (^)())completion
{
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
for (PFObject *object in objects) {
Offer *offer = [Offer MR_findFirstByAttribute:#"offerId" withValue:object.objectId inContext:localContext];
if (offer == nil) {
offer = [Offer MR_createEntityInContext:localContext];
}
// Here I set all the offer values (title, date, etc)...
NSSet *offerSavedSystems = [offer mutableSetValueForKey:#"systems"];
if (offerSavedSystems == nil) {
offerSavedSystems = [[NSMutableSet alloc] init];
}
/* This is a set of all the systems related with the offer */
NSArray *offerSystems = [object objectForKey:#"sistemas"];
NSMutableSet *updatedSystems = [[NSMutableSet alloc] init];
/* Here I query one of my System entities for each in the "offerSystems" array */
for (NSString *systemKey in offerSystems) {
System *system = [System MR_findFirstByAttribute:#"key" withValue:systemKey inContext:localContext];
[updatedSystems addObject:system];
}
offer.systems = updatedSystems;
}
} completion:^(BOOL contextDidSave, NSError *error) {
/* UI update*/
}];
}
The weird this happens inside the last for loop. Despite I'm sure that all the 8 systems are inside my CoreData model, this line
System *system = [System MR_findFirstByAttribute:#"key" withValue:systemKey inContext:localContext];
returns nil
But the most weird thing is that using NSLOG just before the for loop like this
NSLog(#"SYSTEMS %d", [System MR_countOfEntities]);
NSLog(#"SYSTEMS WITH LOCAL CONTEXT %d", [System MR_countOfEntitiesWithContext:localContext]);
I got this
SYSTEMS 8
SYSTEMS WITH LOCAL CONTEXT 0
My Systems are previously saved with this method
+ (void)initializeSystems
{
NSArray *systemsKeys = [[self systems] allKeys];
for (NSString *systemKey in systemsKeys) {
System *system = [System MR_findFirstByAttribute:#"key" withValue:systemKey];
if (system == nil) {
system = [System MR_createEntity];
}
[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
system.key = systemKey;
system.name = [self literalForSystem:systemKey];
system.subscribed = [NSNumber numberWithBool:NO];
}];
}
}
What I'm doing wrong?
Thanks for your time
There are several possible problems with this line of code
System *system = [System MR_findFirstByAttribute:#"key" withValue:systemKey inContext:localContext];
systemKey value does not exist inside all of your entities.
system.key value not setted (or nil)
So, check firstly - fetch all system entities and log 'key' value. Insure that your key really exist.
Secondly,it's better to refactor your code for background saving
+ (void)initializeSystemsWithCompletion:(void (^)())completion
{
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
NSArray *systemsKeys = [[self systems] allKeys];
for (NSString *systemKey in systemsKeys) {
System *system = [System MR_findFirstByAttribute:#"key" withValue:systemKey inContext:localContext];
if (system == nil) {
system = [System MR_createEntityInContext:localContext];
}
system.key = systemKey;
system.name = [self literalForSystem:systemKey];
system.subscribed = [NSNumber numberWithBool:NO];
}
} completion:^(BOOL success, NSError *error) {
}];
}

How does this code use only updates into core data?

This is a SyncEngine from an RW tutorial. I need help understanding how only UPDATED records from the web are fetched and processed into Core Data.
- (void)processJSONDataRecordsIntoCoreData {
NSManagedObjectContext *managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext];
// Iterate over all registered classes --- CHECK!
for (NSString *className in self.registeredClassesToSync) {
if (![self initialSyncComplete]) {
NSDictionary *JSONDictionary = [self JSONDictionaryForClassWithName:className];
NSArray *records = [JSONDictionary objectForKey:#"results"];
for (NSDictionary *record in records) {
[self newManagedObjectWithClassName:className forRecord:record];
}
} else {
NSArray *downloadedRecords = [self JSONDataRecordsForClass:className sortedByKey:#"objectId"];
if ([downloadedRecords lastObject]) {
NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:#"objectId" usingArrayOfIds:[downloadedRecords valueForKey:#"objectId"] inArrayOfIds:YES];
int currentIndex = 0;
//if dl count is < current index, there is an updated object dl from the web
for (NSDictionary *record in downloadedRecords) {
NSManagedObject *storedManagedObject = nil;
//Quick check to see if they indeed match, if they do, update the stored object with remote service objects
if ([storedRecords count] > currentIndex) {
storedManagedObject = [storedRecords objectAtIndex:currentIndex];
}
//Othwerwise its a new object and you need to create a new NSManagedObject to represent it in CDdb
if ([[storedManagedObject valueForKey:#"objectId"] isEqualToString:[record valueForKey:#"objectId"]]) {
[self updateManagedObject:[storedRecords objectAtIndex:currentIndex] withRecord:record];
} else {
[self newManagedObjectWithClassName:className forRecord:record];
}
currentIndex++;
}
}
}
// After all NSMO are created in your context, save it!
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
if (![managedObjectContext save:&error]) {
NSLog(#"Unable to save context for class %#", className);
}
}];
// Cleanup time
[self deleteJSONDataRecordsForClassWithName:className];
[self executeSyncCompletedOperations];
}
[self downloadDataForRegisteredObjects:NO];
}
From what I understand, on the first or initial sync, it fetches JSONDictionaryForClassWithName which reads the downloaded data from disk and creates a newManagedObjectWithClassName.
My confusion is in the update else block. downloadedRecords is populated from JSONDataRecordsForClass which simply calls JSONDictionaryForClassWithName. Then it checks to see if there is at least 1 object in that array. If there is it does this:
NSArray *storedRecords = [self managedObjectsForClass:className sortedByKey:#"objectId" usingArrayOfIds:[downloadedRecords valueForKey:#"objectId"] inArrayOfIds:YES];
This fetches all managedObjectsForClass:sortedByKey which is below:
- (NSArray *)managedObjectsForClass:(NSString *)className sortedByKey:(NSString *)key usingArrayOfIds:(NSArray *)idArray inArrayOfIds:(BOOL)inIds {
__block NSArray *results = nil;
NSManagedObjectContext *managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext];
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:className];
NSPredicate *predicate;
if (inIds) {
predicate = [NSPredicate predicateWithFormat:#"objectId IN %#", idArray];
} else {
predicate = [NSPredicate predicateWithFormat:#"NOT (objectId IN %#)", idArray];
}
[fetchRequest setPredicate:predicate];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:
[NSSortDescriptor sortDescriptorWithKey:#"objectId" ascending:YES]]];
[managedObjectContext performBlockAndWait:^{
NSError *error = nil;
results = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
}];
return results;
}
The next bit which compares the [storedRecords count] > currentIndex is confusing. Can someone please explain this? I think my confusion lies in what the managedObjectsForClass method does with the usingArraysOfIds & inArrayOfIds.
I would expect that at some point it gets the the updatedAt field from the downloaded records and compares it to the updatedAt field of the CoreData fetched records.
This function is processing the stored JSON. The actual remote fetching and updateAt checking happens in downloadDataForRegisteredObjects and mostRecentUpdatedAtDateForEntityWithName.
[storedRecords count] > currentIndex is a bit crazy. Although in defense of the original programmer, writing any decent syncengine will quickly make you go googoo. Basically he needs to work out which records are existing and which ones are new and update the local data store accordingly, that's all.
I had another look and this code is actually horribly broken. It will only works if either you have the same records both locally and remotely. Or if the new objects have an objectId that sort-wise comes after the last object the local store has. Which is not the case with Parse objectId's.
If you are testing with just one device this works because new objects will be inserted locally before being pushed to the server. Therefor you will always have the same amount of records. If additional records get inserted any other way, this code will do weird things.

NSInternalInconsistencyException recursive dirtying confusion

I'm doing my head in trying to figure out an issue I'm having with core-data. I understand what the error means, and I've had it before (and fixed it) but I can't figure out why I'm getting it now.
My app has the following structure :
MPModel -> MPPlace and MPModel -> MPProject
Where MPModel is a subclass of NSManagedObject and MPPlace and MPProject are subclasses of MPModel.
The data model has a relationship between MPPlace and MPProject where MPPlace has-many MPProjects and MPProject belongs-to MPPlace.
When the app loads, it fetches a number of MPPlace objects which works perfectly. When a user selected a place and then selects the projects option, the app attempts to retrieve the list of projects. This is where the app fails however, with the following error
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason:
'Failed to process pending changes before save. The context is still dirty after 100
attempts. Typically this recursive dirtying is caused by a bad validation method,
willSave, or notification handler.'
Each MPModel contains a number of custom methods, including saveAllLocally which simply saves an array of objects to the persistence store if they don't already exist, and loadNestedResources which fetches new objects from the server that are related to the current object. I am finding that the failure is occurring with the loadNestedResources method but I can't figure out why.
The loadNestedResources method looks like this :
- (void) loadNestedResourcesOfType:(Class)type atURL:(NSString *)resURL withBlock:(MPFindObjectsBlock)block
{
if (![type isSubclassOfClass:[MPModel class]]) {
block(nil, nil);
} else {
NSString *url = [NSString stringWithFormat:#"%#%#/%#%#", kMP_BASE_API_URL, [self.class baseURL], self.objID, [type baseURL]];
MPRequest *request = [[MPRequest alloc] initWithURL:url];
// Attempt to see if we already have this relation
NSString *relation = [[MPUtils stripClassName:type].lowercaseString stringByAppendingString:#"s"];
NSSet *relatedObjects = [self valueForKey:relation];
if (relatedObjects && relatedObjects.count > 0) {
// We have some objects so lets exclude these from our request
NSMutableArray *uuids = [NSMutableArray arrayWithCapacity:0];
for (MPModel *obj in relatedObjects) {
[uuids addObject:obj.uuid];
}
[request setParam:[uuids componentsJoinedByString:#";"] forKey:#"exclude_uuids"];
}
[MPUser signRequest:request];
[request setRequestMethod:#"POST"];
[request submit:^(MPResponse *resp, NSError *error) {
if (error) {
if (relatedObjects.count > 0) {
block([relatedObjects allObjects], nil);
} else {
block(nil, error);
}
} else {
// Combine all of our objects
NSMutableArray *allObjects = [[type createListWithResponse:resp] mutableCopy];
if (allObjects.count > 0) {
[allObjects addObjectsFromArray:[relatedObjects allObjects]];
// Make sure they're now all saved in the persistence store
NSArray *savedObjects = [MPModel saveAllLocally:allObjects forEntityName:NSStringFromClass(type)];
for (NSObject *obj in savedObjects) {
[obj setValue:self forKey:[MPUtils stripClassName:self.class].lowercaseString];
}
// Set them as our related objects for this relationship
[self setValue:[NSSet setWithArray:savedObjects] forKey:relation];
[MPModel saveAllLocally:savedObjects forEntityName:NSStringFromClass(type)];
block(allObjects, nil);
} else {
block([relatedObjects allObjects], nil);
}
}
}];
}
}
The methods runs perfectly right up until the second call to saveAllLocally which is where I get the error. The MPModel class also uses the willSave method, which has the following :
- (void) willSave
{
NSDate *now = [NSDate date];
if (!self.updated_at) {
self.updated_at = now;
}
if (!self.created_at) {
self.created_at = now;
}
if (!self.uuid) {
self.uuid = [self createUUID];
}
if (!self.last_sync) {
self.last_sync = now;
}
if ([self isUpdated] && self.changedValues.count > 0) {
if (!self.attribute_updated_at) {
NSDictionary *attributes = [self.entity attributesByName];
NSMutableDictionary *dates = [NSMutableDictionary dictionaryWithCapacity:0];
for (NSString *attr in attributes.allKeys) {
[dates setObject:now forKey:attr];
}
[self setAttributeUpdatedDates:dates];
}
if (_updatedAtSet) {
_updatedAtSet = NO;
} else {
if ([self.changedValues.allKeys containsObject:#"last_sync"]) {
self.updated_at = [self.changedValues objectForKey:#"last_sync"];
} else {
self.updated_at = [NSDate date];
}
_updatedAtSet = YES;
NSDictionary *changed = [self changedValues];
NSMutableDictionary *dates = [[self attributeUpdatedDates] mutableCopy];
for (NSString *key in changed.allKeys) {
[dates setObject:now forKey:key];
}
[self setAttributeUpdatedDates:dates];
}
}
}
From what I can gather, this should be fine as it shouldn't be setting any more values if the _updatedAtSet variable is set to true, however it is still breaking and I cannot figure out why!
Please can someone help me
Thanks
Have solved it.
I just moved the _updatedAtSet = NO; into the didSave method rather than where it is and it's working fine now. Thanks anyway

Resources