Question

I have a table which is populated by a title and image entry. This is done by the following methods:

tablePhotoViewController.m

- (IBAction)takePicture:(UIBarButtonItem *)sender {

// check #1 - make sure our source type is supported
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {

    NSArray *mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];

    // check #2 see if media type includes images
    if ([mediaTypes containsObject:(NSString *)kUTTypeImage]) {

        // create our image picker
        UIImagePickerController *picker = [[UIImagePickerController alloc] init];
        picker.delegate = self;
        picker.sourceType = UIImagePickerControllerSourceTypeCamera;
        picker.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeImage];
        picker.allowsEditing = YES;
        [self  presentViewController:picker animated:YES completion:nil];
    }
}
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// do something with this image
UIImage *imagefromcamerabutton = [info objectForKey:UIImagePickerControllerEditedImage];

// handle the case where editting was not allowed...
if (!imagefromcamerabutton) imagefromcamerabutton = [info objectForKey:UIImagePickerControllerOriginalImage];

// save to photo albumn
ALAssetsLibrary *al = [Utils defaultAssetsLibrary];
[al writeImageToSavedPhotosAlbum:[imagefromcamerabutton CGImage] metadata:nil
                 completionBlock:^(NSURL *assetURL, NSError *error)
 {
     // once we know it's saved, grab the ALAsset and store
     // it in our collection for display later
     ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
     {
         [self.photos addObject:myasset];
         [self.tableView reloadData];
     };

     ALAssetsLibrary *assetslibrary = [Utils defaultAssetsLibrary];
     [assetslibrary assetForURL:assetURL
                    resultBlock:resultblock
                   failureBlock:nil];
 }];
[self dismissImagePicker];
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.photos count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

// Configure the cell...
ALAsset *asset = [self.photos objectAtIndex:indexPath.row];

[cell.imageView setImage:[UIImage imageWithCGImage:[asset thumbnail]]];
[cell.textLabel setText:[NSString stringWithFormat:@"Thing %d", indexPath.row+1]];

return cell;
}

This works well, but the problem is that after the user closes the app, the cell data is erased. I would like these to be able to stay as photos which are continually associated with the table unless the user taps a button to delete it from the array. From my limited understanding of how this could be done it looks like i need to somehow implement NSUserDefaults is that right or is there a better practice to achieve this goal?

Was it helpful?

Solution

NSUserDefaults is loaded completely into memory when it is accessed. This means if you data source contains more than a few items this would be really slow or it could even crash when the phone runs out of memory.

But, when I understand you code correctly you are storing the photos in the camera roll. Therefore you have some kind of URL to the image already (the assetURL in your code).

For a quick and kind of dirty solution (which I find OK for small amounts of data which does not change often, I use NSCoding. So you can add the title and the assetURL into a NSDictionary and add the dictionary to the array of your data source. Then in dealloc call

[NSKeyedArchiver archiveRootObject:self.myDataSourceArray toFile:[self pathToFileInDocumentsDirectory]];

In viewDidLoad you can then get the data back you call:

self.myDataSourceArray = [NSKeyedUnarchiver unarchiveObjectWithFile:[self pathToFileInDocumentsDirectory]];

If the data contains many items or the items are about to change much I tend to use Core Data or Sqlite. How to use those doesn't fit into this answer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top