Почему на ios5 не будет сразу прекращать работу с UIImagePickerController?

У меня есть UITableViewController, который выводит UIImagePickerController, пользователь делает снимок, нажимает кнопку «Использовать», средство выбора отключается, чтобы показать настраиваемый счетчик миниатюр во время обработки изображения, затем счетчик заменяется фактической миниатюрой в конце обработки.

По крайней мере, так это работало в iOS4. Теперь с iOS5 он просто сидит и обрабатывается, пока не закончит, а затем все работает правильно. Но я хочу, чтобы этот счетчик был там, чтобы пользователь знал, что что-то происходит, иначе он выглядит так, как будто он просто завис.

Итак, у меня есть это:

- (void) actionSheet: (UIActionSheet *)actionSheet didDismissWithButtonIndex (NSInteger)buttonIndex {
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];
    picker.delegate = self;
    picker.allowsEditing = NO;
    // yada, yada, yada
    [self presentModalViewController:picker animated:YES];
    [picker release];
}

И затем это вызывается, когда пользователь выбирает «Использовать»:

- (void) imagePickerController: (UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
    [self dismissModalViewControllerAnimated:YES];
    [self performSelectorOnMainThread:@selector(processImage:) withObject:info waitUntilDone:NO];
    animate = true;
}

И затем это вызывается для выполнения обработки во время вращения миниатюры:

- (void) processImage:(NSDictionary *)info
{
    UIImage *image = nil;
    NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];
    // processing of image
    animate = false;
    [activityImageView stopAnimating];
    [activityImageView release];
    [self.tableView reloadData];
}

Как я уже сказал, он отлично работал с iOS4, но с iOS5 не повезло. Так в чем же дело? Средство выбора изображений в конечном итоге закрывается, так почему же оно не закрывается сразу?


person mutatron    schedule 07.12.2011    source источник
comment
Я действительно не знаю, почему это должно иметь значение, но вы пытались заменить [self performSelector... на dispatch_async(dispatch_get_main_queue(), ^{[self processImage:info];});?   -  person NJones    schedule 07.12.2011
comment
Хорошая мысль, но такое же поведение. Хоть что-то новое узнал!   -  person mutatron    schedule 07.12.2011


Ответы (2)


Я не уверен, почему существует несоответствие между iOS4 и iOS5 в этом вопросе. Но ваше описание зависания пользовательского интерфейса вполне соответствует коду, который вы показали. Селектор выполнения в основном потоке делает именно это, выполняя селектор в основном потоке, из которого вы вызываете. Из-за этой настройки от waitUntilDone: до NO бессмысленно, поскольку он не отправляется в другой поток, а просто выполняется по порядку. Вероятно, вы получите желаемые результаты, просто поменяв порядок местами, например Итак:

[self dismissModalViewControllerAnimated:YES];
animate = true;
[self performSelectorOnMainThread:@selector(processImage:) withObject:info waitUntilDone:NO];

Но обратите внимание, что это было бы в лучшем случае рискованно, поскольку я предполагаю, что // processing of image не содержит параллелизма. Я предпочитаю блоки для параллелизма. Кроме того, мне нравятся вложенные блоки, чтобы упростить отслеживание параллелизма, например:

-(void)doSomeStuffInBackground{
    // Prepare for background stuff
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // Do background stuff
        dispatch_async(dispatch_get_main_queue(), ^{
            // Update UI from results of background stuff
        });
    });
}

Поэтому, имея это в виду, я бы предложил что-то более похожее на это:

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
    [self dismissModalViewControllerAnimated:YES];
    [self processImage:info];
}

-(void)processImage:(NSDictionary *)info{
    animate = true;
    UIImage *image = nil;
    NSString* mediaType = [info objectForKey:UIImagePickerControllerMediaType];

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        // processing of image here on background thread

        dispatch_async(dispatch_get_main_queue(), ^{
            // update UI here on main thread
            animate = false;
            [activityImageView stopAnimating];
            [activityImageView release];
            [self.tableView reloadData];
        });
    });
}

Это перенесет основную работу в фоновый поток, чтобы пользовательский интерфейс оставался отзывчивым.

person NJones    schedule 08.12.2011
comment
Идеально! Это делает именно то, что я хочу, и я тоже кое-чему научился. На самом деле, сейчас я припоминаю, что научился чему-то подобному на уроках, которые посещал, но, думаю, это не закрепилось у меня. Спасибо! - person mutatron; 08.12.2011

Попробуй использовать

[[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil]; 

вместо:

[[picker parentViewController] dismissModalViewControllerAnimated: YES];
person Gigi    schedule 24.02.2013
comment
Добро пожаловать в Stack Overflow! Спасибо за ваш пост! Пожалуйста, не используйте подписи/слоганы в своих сообщениях. Ваш пользовательский ящик считается вашей подписью, и вы можете использовать свой профиль для публикации любой информации о себе, которая вам нравится. Часто задаваемые вопросы о подписях/слоганах - person Andrew Barber; 24.02.2013