Search code examples
iosobjective-cuitableviewcore-datacell

Retrieving core data object from cell


I am saving an object from core data to a cell as listed bellow. The URL is being saved to the cell correctly and working great. My problem is that, when a user taps on a cell, I would like the URL that is saved to that cell to be passed to my detailedViewController for use. I have some code that I have tried but the url is nil in the detailedViewController. If you have any better way of accomplishing the same thing, that would be fine. The code is listed bellow -

Here is where I save it to the cell:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = @"Cell";
PhotoCell *cell = (PhotoCell *)[self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (!cell) {
    cell = [[PhotoCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}

// Configure the cell...
FeedEntity *feed = [_fetchedResultsController objectAtIndexPath:indexPath];
NSData *data = feed.imageData;

self.feedImage = [UIImage imageWithData:data];
cell.thumbImage = self.feedImage;

NSData *stringData = feed.urlString;
self.stringForURL = [[NSString alloc] initWithData:stringData encoding:NSUTF8StringEncoding];
self.stringForURL = [self.stringForURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
self.finalURL = [NSURL URLWithString:self.stringForURL];

cell.finalURL = self.finalURL;

return cell;
}

Here is where I retrieve the url from the cell and pass it to the detailedViewController:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];

    // Code to create detailed view and set properties
    self.detailsViewController = [[DetailsViewController alloc] init];

    NSIndexPath *path = [self.tableView indexPathForSelectedRow];
    FeedEntity *feed = [_fetchedResultsController objectAtIndexPath:path];
    NSData *stringData = feed.urlString;
    NSString *stringURL = [[NSString alloc] initWithData:stringData encoding:NSUTF8StringEncoding];
    NSLog(@"Here is the string before: %@", stringURL);
    stringURL = [self.stringForURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *urlForDetail = [NSURL URLWithString:self.stringForURL];

    NSLog(@"Here is the url before it goes to the detailed: %@", urlForDetail);

    self.detailsViewController.finalURL = urlForDetail;

    [self.navigationController pushViewController:self.detailsViewController animated:YES];

}

Save the video (in didFinishPickingMediaWithInfo:):

self.videoURL = [info objectForKey:UIImagePickerControllerMediaURL];

NSData *videoData = [NSData dataWithContentsOfURL:self.videoURL];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingFormat:@"/vid1.mp4"];
self.urlForSave = [NSURL fileURLWithPath:path];

//Look at YES
[videoData writeToFile:path atomically:YES];
[self saveImageAndVideo];

Here is SaveVideoAndPhoto:

- (void)saveImageAndVideo {

    NSManagedObjectContext *context = [self managedObjectContext];

    FeedEntity *feedEntity = [NSEntityDescription insertNewObjectForEntityForName:@"FeedEntity" inManagedObjectContext:context];

    NSData *imageData = UIImageJPEGRepresentation(self.thumbImage, 0.8f);
    self.photoData = imageData;

    NSString *stringForSave = [self.urlForSave absoluteString];
    NSLog(@"URL before save: %@", stringForSave);

    //NSData * stringData = [stringForSave dataUsingEncoding:NSUTF8StringEncoding];

    [feedEntity setValue:imageData forKey:@"imageData"];
    [feedEntity setValue:[NSDate date] forKey:@"timeStamp"];
    [feedEntity setValue: stringForSave forKey:@"urlString"];

    NSError *error = nil;

    if (![self.managedObjectContext save:&error]) {
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    } else {
        NSLog(@"URL's are being saved");
    }
}

Solution

  • Your problem is in the code in cellForRowAtIndexPath:

    self.finalURL = [NSURL URLWithString:self.stringForURL];
    

    You are setting the URL as a property of SELF, which in this case is your viewController. You want to set it on the CELL. Change all that code when you create the cell from self.whatever to cell.whatever if you want to save them as properties of the cell. It might help you if you did some reading up on scope in objective-c.

    Also, on a side note, there are a few things you are doing that are unnecessary. Firstly is this:

    NSIndexPath *path = [self.tableView indexPathForSelectedRow];
    

    You don't need to create an indexPath object inside this function, because you are already provided it by the function itself with the variable indexPath:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    

    Secondly, inside of didSelectRowAtIndexPath, if you want to get the url, you should be doing something like this:

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        // deselect the row if you want the cell to fade out automatically after tapping
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
        // get a reference to the cell that the user tapped
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    
        // get the url from the cell, assuming your cell has a property called finalURL on it that you set some value
        // to originally when it was created
        NSURL *url = cell.finalURL;
    
        // do something with that URL here...
    }
    

    Keep in mind this is slightly unorthodox. You really should get the information from your tableView's datasource. If you have an array of objects that you are using to populate your tableView, it's probably a better idea to simply get the object itself from our array with the given indexPath rather than save the information on the cell as a property and access it that way. I would highly suggest watching some tutorial videos or do some reading up, preferably in the iOS docs themselves, to try to learn best practices for UITableViews.