ABPeoplePickerNavigationController saving larger image takes a LONG time
I use ABPeoplePickerNavigationController to import iPhone Contacts into my app. I recently decided, instead of just saving the thumbnail image, to save the entire image as well. With iPad and possibly needing larger images with different cropping, I think this is the way to go. However, when saving some new contacts after importing, the save is LONG, depending on the size of the photo. No photo and the save is immediate, so I know it has to do with the size of the photo and what I am doing with it. Relevant code is below in case anyone can point out what I am doing wrong...
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)contact {
NSLog(@"%s", __FUNCTION__);
self.selectedThumbnailImage = nil;
self.selectedImage = nil;
if(ABPersonHasImageData(contact)){
self.selectedThumbnailImage = nil;
NSData *imgData = (NSData *)ABPersonCopyImageData(contact);
UIImage *pickedImage = [UIImage imageWithData:imgData];
[imgData release];
self.selectedImage = pickedImage;
CGSize imageSize = pickedImage.size;
CGSize targetSize = CGSizeMake(110.0,120.0);
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
if (CGSizeEqualToSize(imageSize, targetSize) == NO)
{
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor > heightFactor)
scaleFactor = widthFactor; // scale to fit height
else
scaleFactor = heightFactor; // scale to fit width
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the image
if (widthFactor > heightFactor)
{
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else
if (widthFactor < heightFactor)
{
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
UIGraphicsBeginImageContext(targetSize);
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = thumbnailPoint;
thumbnailRect.size.width = scaledWidth;
thumbnailRect.size.height = scaledHeight;
[pickedImage drawInRect:thumbnailRect];
self.selectedThumbnailImage = UIGraphicsGetImageFromCurrentImageContext();
[[NSNotificationCenter defaultCenter] postNotificationName:@"personChanged" object:nil];
UIGraphicsEndImageContext();
}
self.n开发者_JAVA技巧ameFirstString = (NSString *)ABRecordCopyValue(contact, kABPersonFirstNameProperty);
self.nameLastString = (NSString *)ABRecordCopyValue(contact, kABPersonLastNameProperty);
[nameFirstTextField setText:nameFirstString];
[nameLastTextField setText:nameLastString];
self.person.birthday = (NSDate *)ABRecordCopyValue(contact, kABPersonBirthdayProperty);
[self updateRightBarButtonItemState];
[self dismissModalViewControllerAnimated:YES];
return NO;
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{
NSLog(@"%s", __FUNCTION__);
return NO;
}
- (void)saveImage {
// Delete any existing image.
NSManagedObjectContext *context = [[UIApplication sharedDelegate] managedObjectContext];
Image *oldImage = person.image;
if (oldImage != nil) {
[context deleteObject:(NSManagedObject*)oldImage];
}
// Create an image object for the new image.
UIImage *newImage = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:context];
[newImage setValue:selectedImage forKey:@"image"];
[self.person setValue:newImage forKey:@"image"];
}
- (IBAction)save:(id)sender {
NSLog(@"%s", __FUNCTION__);
[self.person setValue:selectedThumbnailImage forKey:@"thumbnailImage"];
[self saveImage];
self.person.nameFirst = nameFirstString;
self.person.nameLast = nameLastString;
NSError *error;
NSManagedObjectContext *context = [[UIApplication sharedDelegate] managedObjectContext];
if (![context save:&error]) {
NSLog(@"AddPersonViewController - addViewControllerDidFinishWithSave - Person MOC save error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
[self.delegate addPersonViewController:self didFinishWithSave:YES didEditPerson:person];
}
EDIT: I changed the saveImage code to the following and got the error 'Illegal attempt to establish a relationship 'person' between objects in different contexts':
- (void)saveImage {
// Delete any existing image.
//NSManagedObjectContext *context = [[UIApplication sharedDelegate] managedObjectContext];
NSLog(@"%s", __FUNCTION__);
NSManagedObjectContext *savingPhotoContext = [[NSManagedObjectContext alloc] init];
self.savingPhotoMOC = savingPhotoContext;
[savingPhotoMOC setPersistentStoreCoordinator:[[[UIApplication sharedDelegate] managedObjectContext] persistentStoreCoordinator]];
[savingPhotoContext release];
Image *oldImage = person.image;
if (oldImage != nil) {
[savingPhotoMOC deleteObject:(NSManagedObject*)oldImage];
}
// Create an image object for the new image.
UIImage *newImage = [NSEntityDescription insertNewObjectForEntityForName:@"Image" inManagedObjectContext:savingPhotoMOC];
[newImage setValue:selectedImage forKey:@"image"];
[newImage setValue:self.person forKey:@"person"];
//[self.person setValue:newImage forKey:@"image"];
NSNotificationCenter *dnc = [NSNotificationCenter defaultCenter];
[dnc addObserver:self selector:@selector(addControllerContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:savingPhotoMOC];
NSError *error;
if (![savingPhotoMOC save:&error]) {
NSLog(@"Occasion View Controller - addViewControllerDidFinishWithSave - Adding MOC save error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
[dnc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:savingPhotoMOC];
self.savingPhotoMOC = nil;
}- (void)addControllerContextDidSave:(NSNotification*)saveNotification {
NSLog(@"%s", __FUNCTION__);
NSManagedObjectContext *context = [[UIApplication sharedDelegate] managedObjectContext];
[context mergeChangesFromContextDidSaveNotification:saveNotification];
}
If it takes long, you should do this the background and either use delegate callback or nsnotification to inform other functions that might be using it when the save is done. you can use GCD or nsoperationqueue...for gcd have a look at 'fiery robot's blog. I like it because he explains things not just give code for copy pasting.
精彩评论