简体   繁体   中英

Why is saving these images to core data taking 17 sec + on the iPhone?

I have been working with Apple's iPhone CoreDateRecipes sample code to learn more about tableviews and core data. I have coded my own test app based off of that sample, and it works well except for one thing. When I choose a photo for the 'recipe', no matter if it is from the camera or the library, when I hit "Done" to leave editing mode, it takes about 15 seconds before returning control to the user. This happens when testing on the device - in simulator, there is still a delay, but it is only 2-4 seconds.

I tested the "edit/done" button without choosing a photo and editing other data, and it saves instantaneously, so I'm pretty sure the image is to blame. Below is the code where it leaves editing mode, and the image processing code - what can I add/change/remove to speed this up? I know these sample code pieces are just proofs of concept, but I can't believe they published an example with such a crappy user experience!

Thanks, as always, for any guidance...let me know if there is any other code you need to see, or you can see the whole sample project here

- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
    [super setEditing:editing animated:animated];
    [self updatePhotoButton];

    nameTextField.enabled = editing;
    overviewTextField.enabled = editing;

    [self.navigationItem setHidesBackButton:editing animated:YES];


    if (!editing) {
        NSManagedObjectContext *context = recipe.managedObjectContext;
        NSError *error = nil;
        if (![context save:&error]) {
            NSLog(@"Error in RecipeDetailViewController:setEditing -- %@, %@",error, [error userInfo]);
            abort();
        }
    }
}


- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)selectedImage editingInfo:(NSDictionary *)editingInfo {

    NSManagedObject *oldImage = recipe.image;
    if (oldImage != nil) {
        [recipe.managedObjectContext deleteObject:oldImage];
    }

    NSManagedObject *image = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:recipe.managedObjectContext];
    recipe.image = image;

    [image setValue:selectedImage forKey:@"image"];
    CGSize size = selectedImage.size;
    CGFloat ratio = 0;
    if (size.width > size.height) {
        ratio = 70.0 / size.width;
    } else {
        ratio = 70.0 / size.height;
    }

    CGRect rect = CGRectMake(0.0, 0.0, ratio * size.width, ratio * size.height);

    UIGraphicsBeginImageContext(rect.size);
    [selectedImage drawInRect:rect];
    recipe.thumbnailImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    [self dismissModalViewControllerAnimated:YES];
}

First, as Gilbert pointed out, example code is not meant for production use and will be slow.

Second, you should not store images in Core Data. The example may show how to do it but it is generally a very bad idea . You should be storing images on disk and then keeping a pointer (file path) to the image in Core Data. There are some exceptions to this rule (very small images) but you should rethink your design.

Lastly, A lot of the slowness you are seeing may not be Core Data related. The image picker code is very slow on its own. I would recommend changing the code to just write to disk and see how slow that is compared to the writing to Core Data. I would be surprised if it was much faster.

Update

You can store small images inside of Core Data and my advice from other posts stands, mores for the desktop than iOS. The reason for this is the cache. On iOS, the cache that Core Data uses is very small. If you store images in the database that are large, you can blow out that cache easily and cause future calls that should be in the cache to hit the disk instead. This is not a hard and fast rule of "don't store binary data" but more of a rule of watch your performance and if you are hitting the disk more than you should, binary data could easily be the cause.

Contacts

With regard to contacts, you can be slower because they are doing things differently than you are and they could easily be using private APIs to access the camera. Because it is Apple, they don't necessarily play by the same rules as us.

I'm not an iPhone developer, but generally, example code does not take into account the user experience. Example code shows examples.

In general, you need to perform expensive (long running) operations in additional threads.

Maybe this blog post will help: Respect the Main Thread

I downloaded the project, built it and ran it in the simulator. I couldn't reproduce your problem. I found that the time it took to save an image was visually instantaneous ie no longer than the view transition.

If you see the same issue on the original, unmodified project, then you have something else going on. Make sure you have the latest version of the project which should be the one at your link. I know there is at least one really old one floating around because I hit it recently.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM