2010-07-09 24 views
7

Tôi có những gì tôi tin là một ứng dụng khá đơn giản vào lúc này dựa trên một vài hướng dẫn được trộn với nhau. Tôi đang sử dụng XCode 3.2.3 trong OSX 10.6.4. Nó bắt đầu như là một tiêu chuẩn iPhone "Window Dựa ứng dụng". Sử dụng giao diện người xây dựng tôi đã thêm một Tab Bar điều khiển bằng cách sử dụng video hướng dẫn O'Reilly ở đây:Ngoại lệ trong ứng dụng iPhone: Chuyển đổi phương thức đã được tiến hành

http://broadcast.oreilly.com/2009/06/tab-bars-and-navigation-bars-t.html

Trong Tab đầu tiên tôi có một UIView tiêu chuẩn với hai nút. Cả hai gọi chức năng tương tự để hiển thị một UIImagePickerController:

-(IBAction) btnPhotoClicked:(id)sender { 
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; 
imagePicker.delegate = self; 
if((UIButton *)sender == btnChoosePhoto) 
{ 
    imagePicker.allowsEditing = YES; 
    imagePicker.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; 
} else { 
    imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; 
} 

[self presentModalViewController:imagePicker animated:YES]; 
[imagePicker release]; 
} 

Tôi đang chạy mã bên trong một giả lập như vậy chỉ bao giờ nhấn nút gọi Chọn Ảnh. Khi đối thoại được phát hành với ảnh được chọn, chức năng này sẽ chạy:

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { 
NSURL *mediaUrl; 

mediaUrl = (NSURL *)[info valueForKey:UIImagePickerControllerMediaURL]; 

if (mediaUrl == nil) 
{ 
    imagePuzzle = (UIImage *) [info valueForKey:UIImagePickerControllerEditedImage]; 
    if(imagePuzzle == nil) 
    { 
     //--- Original Image was selected --- 
     imagePuzzle = (UIImage *) [info valueForKey:UIImagePickerControllerOriginalImage]; 
    } 
    else { 
     //--- Get the edited image --- 
     //--- If it was successful the above valueForKey:UIImagePickerControllerEditedImage 
     //--- would have assigned it already. 
    } 
} 
else { 
    //--- Muppet selected a video 
} 

// Animate the picker window going away 
[picker dismissModalViewControllerAnimated:YES]; 
ImageViewController *imageViewController = [[ImageViewController alloc] init]; 
imageViewController.delegate = self;  
[self presentModalViewController:imageViewController animated:YES]; 
[imageViewController release]; 
} 

Đây là vấn đề của tôi. Tôi đã thử nhiều hacks và iterations khác nhau nhưng đoạn code trên là cách đơn giản nhất để trình bày vấn đề. Khi imageViewController được hiển thị dưới dạng đối thoại phương thức, ngoại lệ sau được ném:

2010-07-09 15:29:29.667 Golovomka[15183:207] *** Terminating app due to uncaught 
exception 'NSInternalInconsistencyException', reason: 'Attempting to begin a modal 
transition from <NewViewController: 0x5915f80> to <ImageViewController: 0x594a350>  
while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear 
to know the current transition has completed' 

Làm cách nào để khắc phục điều này? Tôi đã thử sự chậm trễ và các thủ thuật khác nhưng không thực sự hiểu làm thế nào tôi phải sử dụng viewDidAppear hoặc viewDidDisappear để giúp tôi. Cũng cần lưu ý là một ứng dụng rất cơ bản với một lượt xem đang tải bộ chọn sau đó hiển thị một chế độ xem khác với hình ảnh không tạo ra lỗi. Bất kỳ sự giúp đỡ nào cũng biết ơn.

Trả lời

9

Để giải quyết những vấn đề cụ thể được mô tả ở đây, bạn có thể thêm các phương pháp viewDidAppear trong lớp học của bạn:

-(void)viewDidAppear:(BOOL)animated 
{ 
    if (/*just visited ImagePicker*/) 
    { 
     ImageViewController *imageViewController = [[ImageViewController alloc] init]; 
     imageViewController.delegate = self;  
     [self presentModalViewController:imageViewController animated:YES]; 
     [imageViewController release]; 
    } 
} 

Di chuyển những dòng từ dưới đây gọi của bạn:

[picker dismissModalViewControllerAnimated:YES]; 

Vì vậy, bất cứ khi nào lớp học của bạn self xuất hiện (được hiển thị), nó sẽ gọi viewDidAppear ... Vì đây có thể không phải là thực sự những gì bạn muốn mọi lúc, bạn có thể thêm một số biến để đặt/xóa xác định có hay không hiển thị trung gian imageViewController khi self được hiển thị. Một cái gì đó như "Nếu đến từ bộ chọn hình ảnh, hiển thị imageViewController, nếu không thì không làm gì".

Điều đó nói rằng, imho, đẩy chế độ xem phương thức thường phải được thực hiện để phản hồi lại hành động của người dùng và tôi có thể suy nghĩ lại trải nghiệm người dùng tại đây - ví dụ: thêm một subview thay vì đẩy một cái nhìn phương thức mà bạn có thể làm nơi mà bạn hiện đang có mã - nhưng nếu bạn chỉ chơi xung quanh với một số hướng dẫn mà nên giải quyết NSInternalInconsistencyException. :) Chúc mừng!

+0

Cám ơn những lời khuyên, tôi sẽ cố gắng rằng trong mã của tôi vì nó là gọn gàng hơn những gì tôi đang làm. Tôi đang đẩy chế độ xem phương thức sau khi người dùng đã chụp ảnh hoặc đã chọn ảnh. Ý tưởng ở đây là có một số xử lý hình ảnh có khả năng cường độ cao và tôi muốn hiển thị điều đó một cách khiêm tốn cho người dùng cho đến khi hoàn thành. Vì vậy, có hành động của người dùng liên quan trước khi buộc chế độ xem phương thức. Là một sang một bên, tôi cuối cùng đã giết trường hợp ngoại lệ với điều này:

[trình chọn bỏ quaModalViewControllerĐược điều chỉnh: CÓ]; [picker.view.superview removeFromSuperview];
Diziet

+0

OK picker.view.superview removeFromSuperview. Thực sự thực sự giải pháp xấu, trừ khi bạn thích màn hình trống cho tất cả mọi thứ sau đó! Tôi xây dựng lại các ứng dụng từ đầu cuối cùng bằng cách sử dụng một thanh điều khiển thanh điều hướng trong một ứng dụng thanh tab và làm việc tốt. Trên một lưu ý khác, giải pháp của bạn cũng làm việc. Cảm ơn bạn. Bây giờ rõ ràng hơn nhiều. Tôi đã chỉ làm điều này trong 2 ngày từ một nền C/C++/Java/Perl/bash. – Diziet

0

Tôi đã gặp vấn đề tương tự khi tôi muốn trình bày MFMailComposeViewController ngay lập tức sau khi loại bỏ UIImagePickerController. Heres những gì tôi đã làm:

  1. tôi xóa bảng sao kê [imagePicker release]; từ nơi mà tôi đã trình bày cụ chọn hình ảnh và đặt nó trong didFinishPickingMedia gọi lại.

  2. tôi đã sử dụng [self performSelector:@selector(presentMailComposer:) withObject:image afterDelay:1.0f];

Dưới đây là mã của tôi: Hiển thị hình ảnh Picker

if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { NSArray *media = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];

if ([media containsObject:(NSString*)kUTTypeImage] == YES) { 
     UIImagePickerController *picker = [[UIImagePickerController alloc] init]; 
     [picker setMediaTypes:[NSArray arrayWithObject:(NSString *)kUTTypeImage]]; 
     picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 
     picker.delegate = self; 
     [self presentModalViewController:picker animated:YES]; 
     //[picker release]; 
    } 

} 
else { 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unavailable!" 
                message:@"Could not open the Photo Library." 
                delegate:nil 
              cancelButtonTitle:@"OK" 
              otherButtonTitles:nil]; 
    [alert show]; 
    [alert release]; 
} 

ảnh Picker Đại biểu Callback - didFinishPickingMedia

NSString *mediaType = [info valueForKey:UIImagePickerControllerMediaType];

if([mediaType isEqualToString:(NSString*)kUTTypeImage]) { 
    UIImage *photoTaken = [info objectForKey:@"UIImagePickerControllerOriginalImage"]; 

    //Save Photo to library only if it wasnt already saved i.e. its just been taken 
    if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) { 
     UIImageWriteToSavedPhotosAlbum(photoTaken, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 
    } 

    //Pull up MFMailComposeView Controller 
    [self performSelector:@selector(composeMailWithPhoto:) withObject:photoTaken afterDelay:1.0f]; 
} 

[picker dismissModalViewControllerAnimated:YES]; 
[picker release]; 

Display Thư Composer Xem

if ([MFMailComposeViewController canSendMail]) {

MFMailComposeViewController *mailPicker = [[MFMailComposeViewController alloc] init]; 
    mailPicker.mailComposeDelegate = self; 

    // Fill out the email fields and Attach photograph to mail 
    static NSString *imageType = @"image/jpeg"; 
    NSString *imageName = [NSString stringWithString:@"MyCoffeeCup.jpg"]; 
    NSData *imageData = UIImageJPEGRepresentation(image, 1.0); 

    [mailPicker addAttachmentData:imageData mimeType:imageType fileName:imageName]; 
    [mailPicker setToRecipients:[NSArray arrayWithObject:@"[email protected]"]]; 

    [self presentModalViewController:mailPicker animated:YES]; 
    //[self.navigationController pushViewController:mailPicker animated:YES]; 
    [mailPicker release]; 
} 
else { 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Unavailable!" 
                message:@"This device cannot send emails." 
                delegate:nil 
              cancelButtonTitle:@"OK" 
              otherButtonTitles:nil]; 
    [alert show]; 
    [alert release]; 
} 

2

Tôi chạy vào vấn đề này khá một vài lần. Gần đây tôi đã bắt đầu sử dụng sửa lỗi đơn giản này:

Khi tôi sẽ trình bày một bộ điều khiển chế độ xem ngay lập tức sau khi loại bỏ một bộ điều khiển chế độ xem khác, tôi chỉ đơn giản loại bỏ đối số đầu tiên với đối số NO trong dismissModalViewControllerAnimated:.

Vì chế độ xem thứ hai được trình bày với một hoạt ảnh, bạn hầu như không nhận thấy rằng hình ảnh đầu tiên biến mất nhanh. Và bạn không bao giờ có được xung đột chuyển tiếp.

5

Trong iOS 5.0 trở lên, bạn có thể sử dụng

[self dismissViewControllerAnimated:YES completion:^{ 
    //present another modal view controller here 
}]; 
+0

Đó là khá tiện dụng. – Diziet

+0

Giải quyết vấn đề điều hướng của tôi. Cảm ơn –

Các vấn đề liên quan