用戶選擇頭像功能是最常見的調用相機相冊場景,下面就一這一場景為例簡單介紹一下UIImagePickerController的使用蜻懦。
一、 相關方法和屬性詳解:
1、
+ (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType;
用于判斷設備是否支持某一數據源弄跌。UIImagePickerControllerSourceType是系統(tǒng)枚舉值:
typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
UIImagePickerControllerSourceTypePhotoLibrary,// 圖庫即相簿
UIImagePickerControllerSourceTypeCamera,// 相機
UIImagePickerControllerSourceTypeSavedPhotosAlbum// 相機膠卷
} __TVOS_PROHIBITED;
2、
+ (nullable NSArray<NSString *> *)availableMediaTypesForSourceType:(UIImagePickerControllerSourceType)sourceType;
該方法主要用于獲得相機模式下支持的媒體類型:sourceType是UIImagePickerControllerSourceTypeCamera時打印數組為:("public.image","public.movie")
public.image表示靜態(tài)圖片尝苇,public.movie表示視頻铛只。當然也可以是圖庫或者是相機膠卷的,但是結果只有一個("public.image")
使用:
for (NSString* mediaType in [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera]) {
if ([mediaType isEqualToString: (NSString *)kUTTypeImage]) {
//支持拍照
break;
}
if ([mediaType isEqualToString: (NSString *)kUTTypeMovie]) {
//支持攝像
break;
}
}
從上面的代碼可以看到使用了兩個常量:kUTTypeImage和kUTTypeMovie 這兩個常量糠溜。在這里就要提一下UTI:iOS系統(tǒng)中為了更好的進行類型標識淳玩,而提供的一套共用的規(guī)范,也就是“Uniform Type Identifier”非竿,一般稱為“統(tǒng)一類型標識符”,簡稱為“UTI”蜕着。這兩個常量是使用UTI定義的常量,表示"public.image","public.movie"汽馋∥甓可以查看UTCoreTypes.h 文件, 具體可以自行百度一下UTI-iOS圈盔。(主要是碼農我也了解的不多??····)
3、
+ (BOOL)isCameraDeviceAvailable:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0);
用于判斷設備是否支持前置攝像頭/后置攝像頭悄雅。UIImagePickerControllerCameraDevice是系統(tǒng)枚舉值:
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
UIImagePickerControllerCameraDeviceRear,// 后攝像頭
UIImagePickerControllerCameraDeviceFront // 前攝像頭
} __TVOS_PROHIBITED;
4驱敲、
+ (BOOL)isFlashAvailableForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0);
用于判斷設備前置攝像頭/后置攝像頭是否支持閃光燈。
5宽闲、
+ (nullable NSArray<NSNumber *> *)availableCaptureModesForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0);
獲得指定攝像頭上的可用捕獲模式众眨,返回的是NSNumber *類型,捕獲模式是枚舉類型:
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraCaptureMode) {
UIImagePickerControllerCameraCaptureModePhoto,//拍照模式
UIImagePickerControllerCameraCaptureModeVideo//視頻錄制模式
} __TVOS_PROHIBITED;
e.g :
for (NSNumber* captureMode in [UIImagePickerController availableCaptureModesForCameraDevice:(UIImagePickerControllerCameraDeviceRear)]) {
if ([captureMode integerValue] == UIImagePickerControllerCameraCaptureModePhoto) {
JRLog(@"拍照模式");
}
if ([captureMode integerValue] == UIImagePickerControllerCameraCaptureModeVideo) {
JRLog(@"視頻錄制模式 ");
}
}
6容诬、一些屬性:
@property(nullable,nonatomic,weak) id <UINavigationControllerDelegate, UIImagePickerControllerDelegate> delegate; // 必須遵循里面的兩個代理
@property(nonatomic) UIImagePickerControllerSourceType sourceType; // 指定 ImagePickerController的數據源娩梨,默認是UIImagePickerControllerSourceTypePhotoLibrary
@property(nonatomic,copy) NSArray<NSString *> *mediaTypes;// 設置相機模式或者圖庫、相機膠卷模式下支持的媒體類型览徒,默認是包含kUTTypeImage即("public.image")的數組狈定,所以拍照時可以不用設置;但是當要錄像的時候必須設置习蓬,可以設置為kUTTypeVideo(視頻纽什,但不帶聲音)或者kUTTypeMovie(視頻并帶有聲音)
@property(nonatomic) BOOL allowsEditing NS_AVAILABLE_IOS(3_1); // 是否允許編輯,默認是NO躲叼,關于這里詳見(PS.about-1).
@property(nonatomic) NSTimeInterval videoMaximumDuration NS_AVAILABLE_IOS(3_1); //視頻最大錄制時長芦缰,默認為10分鐘。video properties apply only if mediaTypes includes kUTTypeMovie-僅適用于如果媒體類型(mediaTypes)包括kUTTypeMovie視頻屬性枫慷。
@property(nonatomic) UIImagePickerControllerQualityType videoQuality NS_AVAILABLE_IOS(3_1);//設置視頻的質量让蕾,為枚舉類型 ,關于這里詳見(PS.about-2).
@property(nonatomic) BOOL showsCameraControls NS_AVAILABLE_IOS(3_1); //是否顯示攝像頭控制面板或听,默認為YES探孝。 // 只有sourceType 先設置為UIImagePickerControllerSourceTypeCamera的情況下可用,否則會崩潰
@property(nullable, nonatomic,strong) __kindof UIView * cameraOverlayView NS_AVAILABLE_IOS(3_1); //攝像頭上覆蓋的視圖(浮于UIImagePickerController視圖的最上方)神帅,可用通過這個視圖來自定義拍照或錄像界面再姑。值得注意的是當拍照/錄像完成后該界面依然存在。
@property(nonatomic) CGAffineTransform cameraViewTransform NS_AVAILABLE_IOS(3_1); // 設置攝像頭拍攝角度的形變找御,如 cameraPC.cameraViewTransform = CGAffineTransformMakeRotation(M_PI_2);// 平面旋轉90度
@property(nonatomic) UIImagePickerControllerCameraCaptureMode cameraCaptureMode NS_AVAILABLE_IOS(4_0); // 設置攝像頭捕獲模式元镀,默認是UIImagePickerControllerCameraCaptureModePhoto
@property(nonatomic) UIImagePickerControllerCameraDevice cameraDevice NS_AVAILABLE_IOS(4_0); // 設置攝像頭設備,默認UIImagePickerControllerCameraDeviceRear
@property(nonatomic) UIImagePickerControllerCameraFlashMode cameraFlashMode NS_AVAILABLE_IOS(4_0); // 設置閃光燈模式霎桅,枚舉類型(詳見PS.about-3:)栖疑,默認是UIImagePickerControllerCameraFlashModeAuto.
PS.about-1:
一、調用相機時:
allowsEditing = YES:
allowsEditing = NO:
在設置為NO后滔驶,拍攝后的圖片是不能拖動和縮放的遇革,即不能編輯只能使用原圖。
二、使用圖庫或相機膠卷時:
allowsEditing = YES:
allowsEditing = NO時萝快,只要你選中了圖片不會出現(xiàn)上圖中界面而知直接會調用代理方法锻霎,即無法查看大圖及編輯。
PS.about-2:
該屬性的枚舉類型:
typedef NS_ENUM(NSInteger, UIImagePickerControllerQualityType) {
UIImagePickerControllerQualityTypeHigh = 0, //高清質量
UIImagePickerControllerQualityTypeMedium = 1, // 中等質量揪漩,適合WiFi傳輸
UIImagePickerControllerQualityTypeLow = 2, // 低質量旋恼,適合蜂窩網
UIImagePickerControllerQualityType640x480 NS_ENUM_AVAILABLE_IOS(4_0) = 3, // VGA質量,一般不常用
UIImagePickerControllerQualityTypeIFrame1280x720 NS_ENUM_AVAILABLE_IOS(5_0) = 4,
UIImagePickerControllerQualityTypeIFrame960x540 NS_ENUM_AVAILABLE_IOS(5_0) = 5,
} __TVOS_PROHIBITED;
該屬性默認是 UIImagePickerControllerQualityTypeMedium奄容,如果相機設備不支持調整視頻質量將使用默認值冰更。
PS.about-3:
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraFlashMode) {
UIImagePickerControllerCameraFlashModeOff = -1,// 閃光燈關閉
UIImagePickerControllerCameraFlashModeAuto = 0,// 自動
UIImagePickerControllerCameraFlashModeOn = 1// 打開
} __TVOS_PROHIBITED;
7、
- (void)takePicture NS_AVAILABLE_IOS(3_1); //編程方式拍照昂勒,在該方法執(zhí)行結束會直接調用代理方法
- (BOOL)startVideoCapture NS_AVAILABLE_IOS(4_0);//編程方式開始錄制視頻
- (void)stopVideoCapture NS_AVAILABLE_IOS(4_0);//編程方式停止錄制視頻
二蜀细、代理方法及常見內部操作
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info; // 當拍照/錄像完成或選擇圖片完成后都會走此代理方法
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;// 當點擊原生界面中的取消按鈕后會執(zhí)行此代理方法
值得注意的是picker不能關閉自己所以一般要在這兩個代理方法內執(zhí)行dismiss方法!
對于錄制好的視頻或者照片的一些操作都在- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
內進行一般就是照片和視頻的存儲問題戈盈。
info攜帶信息的key如下所示:
UIKIT_EXTERN NSString *const UIImagePickerControllerMediaType __TVOS_PROHIBITED; // an NSString (UTI, i.e. kUTTypeImage)獲取媒體類型信息
UIKIT_EXTERN NSString *const UIImagePickerControllerOriginalImage __TVOS_PROHIBITED; // a UIImage 獲取原始照片
UIKIT_EXTERN NSString *const UIImagePickerControllerEditedImage __TVOS_PROHIBITED; // a UIImage 獲取編輯后的照片
UIKIT_EXTERN NSString *const UIImagePickerControllerCropRect __TVOS_PROHIBITED; // an NSValue (CGRect) 獲得包含編輯界面的剪裁窗的CGRect值(以此尺寸配合原圖得到的新圖為正方形圖奠衔,同時該圖旋轉了90度)
UIKIT_EXTERN NSString *const UIImagePickerControllerMediaURL __TVOS_PROHIBITED; // an NSURL //獲取拍攝后圖片或者視頻路徑(在SourceType為UIImagePickerControllerSourceTypeCamera時可以獲取到)
UIKIT_EXTERN NSString *const UIImagePickerControllerReferenceURL NS_AVAILABLE_IOS(4_1) __TVOS_PROHIBITED; //選取到的圖片或者視頻所在素材庫的URL(在SourceType不為UIImagePickerControllerSourceTypeCamera時可以獲取到)
UIKIT_EXTERN NSString *const UIImagePickerControllerMediaMetadata NS_AVAILABLE_IOS(4_1) __TVOS_PROHIBITED; // 獲取對象的元數據在SourceType為UIImagePickerControllerSourceTypeCamera時可以獲取到)
UIKIT_EXTERN NSString *const UIImagePickerControllerLivePhoto NS_AVAILABLE_IOS(9_1) __TVOS_PROHIBITED; // a PHLivePhoto,得到LivePhoto對象
關于圖片和視頻的保存到相簿奕谭,系統(tǒng)有幾個擴展方法:
UIKIT_EXTERN void UIImageWriteToSavedPhotosAlbum(UIImage *image, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo) __TVOS_PROHIBITED;
//將照片保存到相簿涣觉,其回調方法是:
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
UIKIT_EXTERN BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath) NS_AVAILABLE_IOS(3_1) __TVOS_PROHIBITED;
// 是否允許視頻保存到相簿
UIKIT_EXTERN void UISaveVideoAtPathToSavedPhotosAlbum(NSString *videoPath, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo) NS_AVAILABLE_IOS(3_1) __TVOS_PROHIBITED;
// 將視頻保存到相簿痴荐,其回調方法是:
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
e.g:
// UIImagePickControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
//以下均是在使用攝像頭拍照情況下血柳,在使用相冊或圖庫功能時大致相同
// 獲取媒體類型信息
NSString *mediaType=[info objectForKey:UIImagePickerControllerMediaType];
if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) {//如果是拍照
UIImage *image;
//如果允許編輯則獲得編輯后的照片,否則獲取原始照片
if (picker.allowsEditing) {
image=[info objectForKey:UIImagePickerControllerEditedImage];//獲取編輯后的照片
}else{
image=[info objectForKey:UIImagePickerControllerOriginalImage];//獲取原始照片
}
/*
CGRect cropRect = [[info objectForKey:UIImagePickerControllerCropRect] CGRectValue];
UIImage * cropImage=[info objectForKey:UIImagePickerControllerOriginalImage];
UIImage *rotatedOriginalImage = [cropImage imageRotatedByDegrees:90.0];
CGImageRef imageRef = CGImageCreateWithImageInRect(rotatedOriginalImage.CGImage, cropRect);
UIImage * resultImage = [UIImage imageWithCGImage:imageRef];
//以此法獲得的圖片即為編輯后的圖片其中-imageRotatedByDegrees: 方法是將圖片順時針轉動90度的方法
*/
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image: didFinishSavingWithError: contextInfo:), nil);// 若保存到相簿后沒有其他操作可以:UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
}else if([mediaType isEqualToString:(NSString *)kUTTypeMovie]){//如果是錄制視頻
NSURL *url=[info objectForKey:UIImagePickerControllerMediaURL];//視頻路徑
NSString *urlStr=[url path];
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(urlStr)) {
//保存視頻到相簿生兆,注意也可以使用ALAssetsLibrary來保存
UISaveVideoAtPathToSavedPhotosAlbum(urlStr, self, @selector(video:didFinishSavingWithError:contextInfo:), nil);//保存視頻到相簿
}
}
[picker dismissViewControllerAnimated:YES completion:^{ }];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissViewControllerAnimated:YES completion:^{ }];
}
// 照片保存到相簿的回調
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (error) {
NSLog(@"保存照片過程中發(fā)生錯誤难捌,錯誤信息:%@",error.localizedDescription);
}else{
NSLog(@"照片保存成功.");
}
}
// 視頻保存到相簿的回調
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (error) {
NSLog(@"保存視頻過程中發(fā)生錯誤,錯誤信息:%@",error.localizedDescription);
}else{
NSLog(@"視頻保存成功.");
//錄制完之后可以使用AVPlayer自動播放
NSURL *url=[NSURL fileURLWithPath:videoPath];
NSLog(@"視頻路徑=%@", url);
}
}
//該方法是UIImage的分類中自定義的方法鸦难,其中DegreesToRadians()是一個宏定義:#define DegreesToRadians(x) (M_PI*(x)/180.0)// 將度數轉化成弧度
- (UIImage *)imageRotatedByDegrees:(CGFloat)degrees{
UIView *rotatedViewBox = [[UIView alloc] initWithFrame:CGRectMake(0,0,self.size.height, self.size.width)];
CGAffineTransform t = CGAffineTransformMakeRotation(DegreesToRadians(degrees));
rotatedViewBox.transform = t;
CGSize rotatedSize = rotatedViewBox.frame.size;
UIGraphicsBeginImageContext(rotatedSize);
CGContextRef bitmap = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(bitmap, rotatedSize.width/2, rotatedSize.height/2);
CGContextRotateCTM(bitmap, DegreesToRadians(degrees));
CGContextScaleCTM(bitmap, 1.0, -1.0);
CGContextDrawImage(bitmap, CGRectMake(-self.size.height / 2, -self.size.width / 2, self.size.height, self.size.width), [self CGImage]);
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
三根吁、關于界面的一些問題(會不斷添加~)
1、原生界面中調用起UIImagePickerController后會發(fā)現(xiàn)所有控件上名稱都是英文的合蔽,若想改為中文有很簡單的一種方法:PROJECT --> Info --> Localizations 然后添加簡體中文即可击敌。