ABPeoplePickerNavigationController сохранение большого изображения занимает много времени - PullRequest
1 голос
/ 27 сентября 2011

Я использую ABPeoplePickerNavigationController для импорта контактов iPhone в мое приложение.Недавно я решил вместо сохранения миниатюры сохранить все изображение.С iPad и, возможно, нуждающимися в больших изображениях с другим кадрированием, я думаю, что это путь.Однако при сохранении некоторых новых контактов после импорта сохранение выполняется долго, в зависимости от размера фотографии.Нет фотографии, и сохранение происходит немедленно, поэтому я знаю, что это связано с размером фотографии и с тем, что я с ней делаю.Соответствующий код приведен ниже на случай, если кто-то может указать, что я делаю неправильно ...

    - (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.nameFirstString = (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];
}

РЕДАКТИРОВАТЬ: я изменил код saveImage на следующее и получил ошибку «Незаконная попытка установить отношения» человека'между объектами в разных контекстах':

- (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];  

}

1 Ответ

1 голос
/ 10 октября 2011

Если это займет много времени, вы должны сделать это в фоновом режиме и либо использовать обратный вызов делегата, либо nsnotification, чтобы сообщить другим функциям, которые могут его использовать, когда сохранение будет выполнено.вы можете использовать GCD или nsoperationqueue ... для gcd посмотрите блог блога огненного робота.Мне это нравится, потому что он объясняет вещи, а не просто дает код для вставки копий.

...