在 Beginning iPhone3 Development 書中,關於 Camera 的章節範例,主要是以 UIViewerController 下的 ModalView ( - (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated ) 模式來呈現擷取到的照片,這個模式下的照片並非全螢幕,仍保留一些 Nav Bar 或者 Tool Bar,跟一般看到的 app 可以在拍照完以後在全螢幕模式下編輯不太一樣。
在 Apple Developer 網站當中有一個 PhotoPicker 的範例,主要就是在演示,如何不使用 ModalView 的方式取得 camera 所拍攝到的原始影像,在將這個影像填入你要呈現的 View 當中。
該範例當中宣告了兩個 ViewController:MyViewController 和 OverlayViewController,前者主要就是客製化的 View 想要用來避開 ModalView 模式的方式。後者的 .h 如下程式碼宣告,這個 class 當中包含了一個 UIImageViewController 並且還有一個 遵守 OverlayViewControllerDelegate 協定的成員 "delegate"。
@protocol OverlayViewControllerDelegate; @interface OverlayViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate> { id <OverlayViewControllerDelegate> delegate; UIImagePickerController *imagePickerController; @private ... } @property (nonatomic, assign) id <OverlayViewControllerDelegate> delegate; @property (nonatomic, retain) UIImagePickerController *imagePickerController; ... @end @protocol OverlayViewControllerDelegate - (void)didTakePicture:(UIImage *)picture; - (void)didFinishWithCamera; @end
可以看到這個 OverlayViewControllerDelegate 當中列出了兩個必要實現的方法 didTakePicture 和 didFinishWithCamera。這兩個方法的名稱看起來像是系統發出的事件,但是先前提到,有關照相相關的任務主要是以 UIImagePickerController 這個 class 所控制,所以來看看 OverlayViewControllerDelegate 的 .m 檔。
#pragma mark - #pragma mark UIImagePickerControllerDelegate // this get called when an image has been chosen from the library or taken from the camera // - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image = [info valueForKey:UIImagePickerControllerOriginalImage]; // give the taken picture to our delegate if (self.delegate) [self.delegate didTakePicture:image]; if (![self.cameraTimer isValid]) [self finishAndUpdate]; } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [self.delegate didFinishWithCamera]; // tell our delegate we are finished with the picker } @end
可以看到在實現 UIImagePickerControllerDellegate 的兩個方法當中,偷偷地把事件和影像的資訊 委派給 OverlayViewControllerDelegate protocol 的方法,那麼誰負責做這個 protocol 當中描述的這兩件事呢,答案就是 MyViewController!
- (void)viewDidLoad { self.overlayViewController = [[[OverlayViewController alloc] initWithNibName:@"OverlayViewController" bundle:nil] autorelease]; // as a delegate we will be notified when pictures are taken and when to dismiss the image picker self.overlayViewController.delegate = self; self.capturedImages = [NSMutableArray array]; if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { // camera is not on this device, don't show the camera button NSMutableArray *toolbarItems = [NSMutableArray arrayWithCapacity:self.myToolbar.items.count]; [toolbarItems addObjectsFromArray:self.myToolbar.items]; [toolbarItems removeObjectAtIndex:2]; [self.myToolbar setItems:toolbarItems animated:NO]; } } // as a delegate we are being told a picture was taken - (void)didTakePicture:(UIImage *)picture { [self.capturedImages addObject:picture]; } // as a delegate we are told to finished with the camera - (void)didFinishWithCamera { [self dismissModalViewControllerAnimated:YES]; if ([self.capturedImages count] > 0) { if ([self.capturedImages count] == 1) { // we took a single shot [self.imageView setImage:[self.capturedImages objectAtIndex:0]]; } else { // we took multiple shots, use the list of images for animation self.imageView.animationImages = self.capturedImages; if (self.capturedImages.count > 0) // we are done with the image list until next time [self.capturedImages removeAllObjects]; self.imageView.animationDuration = 5.0; // show each captured photo for 5 seconds self.imageView.animationRepeatCount = 0; // animate forever (show all photos) self.imageView.startAnimating; } } }
上面 MyViewController 實現碼當中可以看到,他包含了一個 OverlayViewController 物件,並且他將該物件的代理設定為 "自己" ( self.overlayViewController.delegate = self; ),最後他實現了這個 OverlayViewControllerDelegate 這 protocol 的兩個方法,將 UIImagePickerController 得到的影像資料神奇的存到自己的成員 capturedImages 當中。
簡而言之,OverlayViewController 將 UIImagePickerControllerDelegate 和 UIImagePickerController 包裝起來,所以富有預設的圖片顯示功能,但是他並沒有用 Modal 的方式,而是將他取得的照片,傳給自己的 delegate 成員。而 MyViewController 有一個 OverlayController 成員,又將自己指向 OverlayController 的 delegate 成員。因此等效於 UIImagePickerController 把取得的照片傳給 MyViewController。
......
No comments:
Post a Comment