Talha Ch Talha Ch - 2 months ago 19
iOS Question

Removed Entity is again found by findFirstByAttribute in MagicalRecord

I'm implementing Favorite scenario using in my app using MagicalRecord a CoreData Wrapper. I'm searching for the value that if the attribute is found in my entity it'll remove it as fav or else it'll add it to fav. Do here

DX *foundDX = [DX MR_findFirstByAttribute:@"code" withValue:cell.DXCodeName.text];
foundDX is the value I'm checking for.
I've a UISearchBar added to my tableView. So when the view is loaded it displays the already fav items which use can un-fav. If user search and select an item it successfully adds it to fav and successfully remove it from data model. But if I again click on fav button it crashes.

if (!foundDX.code) {
//If we are always getting into here that means that either foundDX is nil
//or the code is nil so you need to verify the logic around that.
if (indexPath != nil)
{
if (!_AddEditDX) {
self.AddEditDX = [DX MR_createEntity];
}
[self.AddEditDX setCode:cell.DXCodeName.text];
[self.AddEditDX setDescriptions:cell.DXDescText.text];
[self.AddEditDX setIsFav:[NSNumber numberWithInt:1]];

[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
[self.favDXArray addObject:self.AddEditDX];
[self fetchFavDX];

[cell.DXFavButton setImage:[UIImage imageNamed:@"star_filled"] forState:UIControlStateNormal];
[KSToastView ks_showToast:@"Added to Favourite" duration:1.0f];

}
} else if(self.favDXArray.count > indexPath.row) {
//You can get rid of the if(foundDX.code) because this is the else block to not having it so we must have it.
//Only thing to worry about is the array size
NSLog(@"count is: %ld and row is: %ld",_favDXArray.count, (long)indexPath.row);
DX *tempDX = [self.favDXArray objectAtIndex:indexPath.row];
[tempDX MR_deleteEntity];

[cell.DXFavButton setImage:[UIImage imageNamed:@"star_blank"] forState:UIControlStateNormal];
[self.favDXArray removeObjectAtIndex:indexPath.row];
[[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
[KSToastView ks_showToast:@"Removed from Favourite" duration:1.0f];
}


By Applying some breakpoints I found that:
Suppose code is
E45
and
foundDX
didn't found it for the first time and added it to the data model. Then on pressing fav button again it removes it and in real it did removed it. But if I again tap on fav button the foundDX is still
E45
and hence it crashes. But if I close the app and run it again
E45
is no longer there.


UPDATE

I've updated the code above. I was using
fetchFavDX
in
viewDidLoad
so I tried calling it in the method as updated in the code above. Whereas in
fetchFavDX
I'm doing this:

-(void)fetchFavDX {
self.favDXArray = [NSMutableArray arrayWithArray:[DX MR_findAllSortedBy:@"code" ascending:YES]];
}


Now it is working fine for the first two times meaning add/remove/add/remove. After that it only runs the block
if (!foundDX.code)
meaning it is not getting into the else part.

Answer

You should check that the self.favDXArray count is longer than the indexpath.row so that there is something there to actually remove/retrieve. It would be something like this:

if(self.favDXArray.count > indexPath.row){
    DX *tempDX = [self.favDXArray objectAtIndex:indexPath.row];
    [tempDX MR_deleteEntity];
    [cell.DXFavButton setImage:[UIImage imageNamed:@"star_blank"] forState:UIControlStateNormal];
    [self.favDXArray removeObjectAtIndex:indexPath.row];
    [KSToastView ks_showToast:@"Removed from Favourite" duration:1.0f];
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
}

Update

if (!foundDX.code) {
 //If we are always getting into here that means that either foundDX is nil 
//or the code is nil so you need to verify the logic around that. 
    if (indexPath != nil)
    {
        self.AddEditDX = [DX MR_createEntity];
        [self.AddEditDX setCode:cell.DXCodeName.text];
        [self.AddEditDX setDescriptions:cell.DXDescText.text];
        [self.AddEditDX setIsFav:[NSNumber numberWithInt:1]];

        [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
        [self.favDXArray addObject:self.AddEditDX];
        [self fetchFavDX];

        [cell.DXFavButton setImage:[UIImage imageNamed:@"star_filled"] forState:UIControlStateNormal];
        [KSToastView ks_showToast:@"Added to Favourite" duration:1.0f];

    }
} else if(self.favDXArray.count > indexPath.row) {
//You can get rid of the if(foundDX.code) because this is the else block to not having it so we must have it. 
//Only thing to worry about is the array size
    NSLog(@"count is: %ld and row is: %ld",_favDXArray.count, (long)indexPath.row);
    DX *tempDX = [self.favDXArray objectAtIndex:indexPath.row];
    [tempDX MR_deleteEntity];

    [cell.DXFavButton setImage:[UIImage imageNamed:@"star_blank"] forState:UIControlStateNormal];
    [self.favDXArray removeObjectAtIndex:indexPath.row];
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    [KSToastView ks_showToast:@"Removed from Favourite" duration:1.0f];
}

Make sure that the method to get foundDX is returning what you're expecting. Also make sure that the add/remove is leaving you in the state you expect to be in i.e. that you have the content you have added or removed

Comments