2016.07.08 15:04* 字数 1837 阅读 6066评论 6喜欢 26赞赏 1
问题
在项目中,选择照片或拍照的功能很长见,由于我之前采用系统自带的UIimagePickViewController遇到一点问题:
UIImagePickViewController
UIImagePickerController是iOS系统提供的和系统的相册和相机交互的一个类,可以用来获取相册的照片,也可以调用系统的相机拍摄照片或者视频。该类的继承结构是:
UIImagePickerController-->UINavigationController-->UIViewController-->UIResponder-->NSObject
官方文档中对于该类的说明是:
该类只支持竖屏模式,为了保证该类被原样使用,它不支持子类,并且它的视图层次是私有的不能被修改,只支持自定义cameraOverlayView属性来展示更多信息以及和用户的交互。
由于该类继承自UINavgationController,所以在使用过程中一般实现UIImagePickerControllerDelegate和UINavigationControllerDelegate这两个代理,可以利用navgation的push 和pop操作自定义界面实现更复杂的交互效果。
下面具体分析该类的一些方法和属性.
UIImagePickViewController之常用属性
@property (nullable, nonatomic, weak) id <UINavigationControllerDelegate, UIImagePickerControllerDelegate> delegate;
该对象的代理需要实现UINavigationControllerDelegate和UIImagePickerControllerDelegate协议,nullable是xcode6.3之后引入的nullability annotations特性,主要用于在OC和swift之间的转换。这一特性主要包含两个新的类型注释nullable和nonnull,用于表示对象是否可以是NULL或nil
@property (nonatomic) UIImagePickerControllerSourceType sourceType; // default value is UIImagePickerControllerSourceTypePhotoLibrary.
sourceType用于指定要访问的系统的媒体类型。UIImagePickerControllerSourceType支持以下3种枚举类型,默认值是图片库
typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) { UIImagePickerControllerSourceTypePhotoLibrary,//照片库模式。图像选取控制器以该模式显示时会浏览系统照片库的根目录。 UIImagePickerControllerSourceTypeCamera, //相机模式,图像选取控制器以该模式显示时可以进行拍照或摄像。 UIImagePickerControllerSourceTypeSavedPhotosAlbum //相机胶卷模式,图像选取控制器以该模式显示时会浏览相机胶卷目录。};
@property (nonatomic, copy) NSArray<NSString *> *mediaTypes;
mediaTypes用于设置相机支持的功能,拍照或者是视频,返回值类型可以是kUTTypeMovie视频和kUTTypeImage拍照
const CFStringRef kUTTypeAudiovisualContent ;抽象的声音视频
const CFStringRef kUTTypeMovie ;抽象的媒体格式(声音和视频)
const CFStringRef kUTTypeVideo ;只有视频没有声音
const CFStringRef kUTTypeAudio ;只有声音没有视频
const CFStringRef kUTTypeQuickTimeMovie ;
const CFStringRef kUTTypeMPEG ;
const CFStringRef kUTTypeMPEG4 ;
const CFStringRef kUTTypeMP3 ;
const CFStringRef kUTTypeMPEG4Audio ;
const CFStringRef kUTTypeAppleProtectedMPEG4Audio;
const CFStringRef kUTTypeImage ;抽象的图片类型
const CFStringRef kUTTypeJPEG ;
const CFStringRef kUTTypeJPEG2000 ;
const CFStringRef kUTTypeTIFF ;
const CFStringRef kUTTypePICT ;
const CFStringRef kUTTypeGIF ;
const CFStringRef kUTTypePNG ;
const CFStringRef kUTTypeQuickTimeImage ;
const CFStringRef kUTTypeAppleICNS const CFStringRef kUTTypeBMP;
const CFStringRef kUTTypeICO;
@property (nonatomic) BOOL showsCameraControls NS_AVAILABLE_IOS(3_1);
@property (nonatomic) BOOL allowsEditing NS_AVAILABLE_IOS(3_1); // replacement for -allowsImageEditing; default value is NO.
@property (nonatomic) BOOL allowsImageEditing NS_DEPRECATED_IOS(2_0, 3_1);
@property (nonatomic) UIImagePickerControllerCameraCaptureMode cameraCaptureMode NS_AVAILABLE_IOS(4_0); // default is UIImagePickerControllerCameraCaptureModePhoto
@property (nonatomic) UIImagePickerControllerCameraDevice cameraDevice NS_AVAILABLE_IOS(4_0); // default is UIImagePickerControllerCameraDeviceRear
@property (nonatomic) UIImagePickerControllerCameraFlashMode cameraFlashMode
@property (nonatomic) CGAffineTransform cameraViewTransform NS_AVAILABLE_IOS(3_1); // set the transform of the preview view.
@property (nullable, nonatomic,strong) __kindof UIView *cameraOverlayView NS_AVAILABLE_IOS(3_1); // set a view to overlay the preview view.
当sourceType是camera的时候,这几个属性有效,否则抛出异常。
NS_ENUM(NSInteger, UIImagePickerControllerCameraCaptureMode) {
UIImagePickerControllerCameraCaptureModePhoto,//photo
UIImagePickerControllerCameraCaptureModeVideo//video
};
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraDevice) {
UIImagePickerControllerCameraDeviceRear,//后摄像头(默认)
UIImagePickerControllerCameraDeviceFront//前摄像头
};
typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraFlashMode) {
UIImagePickerControllerCameraFlashModeOff = -1,//关闭闪关灯
UIImagePickerControllerCameraFlashModeAuto = 0,//自动
UIImagePickerControllerCameraFlashModeOn = 1//开启闪关灯
};
@property(nonatomic) NSTimeInterval videoMaximumDuration NS_AVAILABLE_IOS(3_1); // default value is 10 minutes.
@property(nonatomic) UIImagePickerControllerQualityType videoQuality NS_AVAILABLE_IOS(3_1);
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,//1280*720的分辨率
UIImagePickerControllerQualityTypeIFrame960x540 NS_ENUM_AVAILABLE_IOS(5_0) = 5,//960*540分辨率
};
UIImagePickViewController之类方法
@interface UIImagePickerController : UINavigationController <NSCoding>
+ (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType; // returns YES if source is available (i.e. camera present)
+ (nullable NSArray<NSString *> *)availableMediaTypesForSourceType:(UIImagePickerControllerSourceType)sourceType; // returns array of available media types (i.e. kUTTypeImage)
+ (BOOL)isCameraDeviceAvailable:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0); // returns YES if camera device is available
+ (BOOL)isFlashAvailableForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0); // returns YES if camera device supports flash and torch.
+ (nullable NSArray<NSNumber *> *)availableCaptureModesForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDevice NS_AVAILABLE_IOS(4_0);
UIImagePickViewController之对象方法
- (void)takePicture NS_AVAILABLE_IOS(3_1);
- (BOOL)startVideoCapture NS_AVAILABLE_IOS(4_0);
- (void)stopVideoCapture NS_AVAILABLE_IOS(4_0);
UIImagePickViewController之代理方法
@protocol UIImagePickerControllerDelegate<NSObject>
@optional
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(nullable NSDictionary<NSString *,id> *)editingInfo NS_DEPRECATED_IOS(2_0, 3_0);
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info;
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
@end
UIKIT_EXTERN NSString *const UIImagePickerControllerMediaType; //指定用户选择的媒体类型
UIKIT_EXTERN NSString *const UIImagePickerControllerOriginalImage; // 原始图片
UIKIT_EXTERN NSString *const UIImagePickerControllerEditedImage; // 修改后的图片
UIKIT_EXTERN NSString *const UIImagePickerControllerCropRect; // 裁剪尺寸
UIKIT_EXTERN NSString *const UIImagePickerControllerMediaURL; // 媒体的URL
UIKIT_EXTERN NSString *const UIImagePickerControllerReferenceURL NS_AVAILABLE_IOS(4_1); // 原件的URL
UIKIT_EXTERN NSString *const UIImagePickerControllerMediaMetadata //当数据来源是相机的时候获取到的静态图像元数据,可以使用phtoho框架进行处理
UIImagePickViewController之C语言函数(保存图片或视频)
UIKIT_EXTERN void UIImageWriteToSavedPhotosAlbum(UIImage *image, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo);
UIKIT_EXTERN BOOL UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath) NS_AVAILABLE_IOS(3_1);
UIKIT_EXTERN void UISaveVideoAtPathToSavedPhotosAlbum(NSString *videoPath, __nullable id completionTarget, __nullable SEL completionSelector, void * __nullable contextInfo) NS_AVAILABLE_IOS(3_1);
以上便是系统UIImagePickViewController的所有属性和方法的简单介绍
问题解决方案
由于使用设置allowEditing = YES属性后,开启摄像头拍照后直接进入系统自定义的裁剪界面,但是在这个界面,从摄像头拍摄过来的照片无法拖动裁剪,仅仅从相册选择过来的照片是可以拖动进行裁剪的,那么我们就决定裁剪界面不使用系统自带的,而自定义一个裁剪界面.
在UIImagePickViewController的代理方法里
#pragma UIImagePickerController Delegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *portraitImg = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
YYImageClipViewController *imgClipVC = [[YYImageClipViewController alloc] initWithImage:portraitImg cropFrame:CGRectMake(0, 100.0f, self.view.frame.size.width, self.view.frame.size.width) limitScaleRatio:3.0];
imgClipVC.delegate = self;
[picker pushViewController:imgClipVC animated:NO];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissViewControllerAnimated:YES completion:nil];
}
HZImageCropperViewController是我自定义的一个裁剪界面,通过这个控制器的两个代理方法,得到裁剪后的照片
- (void)imageClip:(YYImageClipViewController *)clipViewController didFinished:(UIImage *)editedImage
{
//保存图片
NSString *imageFilePath = [UIImage saveImage:editedImage];
//上传七牛服务器
[self upImageFilePath:imageFilePath];
//隐藏裁剪界面
[clipViewController dismissViewControllerAnimated:YES completion:nil];
}
- (void)imageClipDidCancel:(YYImageClipViewController *)clipViewController
{
[clipViewController dismissViewControllerAnimated:YES completion:nil];
}
下面附上一个demo,里面包含裁剪界面的源代码,可供大家参考
原文:https://www.cnblogs.com/sundaysgarden/p/10397016.html