参考:
打开相册和相机的ZLPhotoBrowser:https://github.com/longitachi/ZLPhotoBrowser
QBImagePicker:https://github.com/questbeat/QBImagePicker
图片裁剪
VPImageCropper:https://github.com/windshg/VPImageCropper
TZLocationManager:https://www.jianshu.com/p/8d4a2d4543ae
===注意:打开相机,点击选择完照片后,会调用控制器的代理方法:-(void)viewwillAppear{}
************************系统相机封装成分类***************
使用:
/**//相机获取权限,打开系统相册,调用该系统相机拍照或者录像使用:
[self CameraGetAuthory:2 isOpenAlbum:YES];//调用系统相册
[self CameraGetAuthory:0 isOpenAlbum:NO];//调用系统相机拍照和录像
[self CameraGetAuthory:1 isOpenAlbum:NO];//调用系统相机拍照
[self CameraGetAuthory:2 isOpenAlbum:NO];//调用系统相机录像*******#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN@interface UIViewController (CameraGetAuthory)<UIImagePickerControllerDelegate,UINavigationControllerDelegate>/**parama1:0表示照相和录像,1表示照相,2表示录像param2:YES表示打开相册,NO表示打开相机*/
-(void)CameraGetAuthory:(NSInteger )index isOpenAlbum:(BOOL)isOpenAlbum;
;
@endNS_ASSUME_NONNULL_END**********//#import "UIViewController+CameraGetAuthory.h"
#import <AVFoundation/AVFoundation.h>
#import <MobileCoreServices/MobileCoreServices.h>
@implementation UIViewController (CameraGetAuthory)
-(void)CameraGetAuthory:(NSInteger )index isOpenAlbum:(BOOL)isOpenAlbum{AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];//获取摄像头if (device) {AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];//判断用户是否有权限访问相机if (status == AVAuthorizationStatusNotDetermined) {//请求权限[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {if (granted) {dispatch_async(dispatch_get_main_queue(), ^{});// [self useCameraGetImageOrVideo:@"image"];// 用户第一次同意了访问相机权限if(!isOpenAlbum){[self useCameraGetImageOrVideo:index];//index---0照相和录像,1照相,2录像}else{[self openSystemAlbum];//打开系统相册}} else {// 用户第一次拒绝了访问相机权限}}];} else if (status == AVAuthorizationStatusAuthorized) { // 用户允许当前应用访问相机if(!isOpenAlbum){[self useCameraGetImageOrVideo:index];//index---0照相和录像,1照相,2录像}else{[self openSystemAlbum];//打开系统相册}} else if (status == AVAuthorizationStatusDenied) { // 用户拒绝当前应用访问相机UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"⚠️ 警告" message:@"请去-> [设置 - 隐私 - 相机 - SGQRCodeExample] 打开访问开关" preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction *alertA = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {}];[alertC addAction:alertA];// [self presentViewController:alertC animated:YES completion:nil];} else if (status == AVAuthorizationStatusRestricted) {NSLog(@"因为系统原因, 无法访问相册");}} else {UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"未检测到您的摄像头" preferredStyle:(UIAlertControllerStyleAlert)];UIAlertAction *alertA = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {}];[alertC addAction:alertA];[self presentViewController:alertC animated:YES completion:nil];}
}
//打开系统的相册
-(void)openSystemAlbum{
//获取方式1:通过相册(呈现全部相册,以文件夹形式展示),UIImagePickerControllerSourceTypePhotoLibrary//获取方式2,通过相机,UIImagePickerControllerSourceTypeCamera只能拍照//获取方法3,通过相册(呈现全部图片,打开文件夹展示文件夹里面的内容)UIImagePickerControllerSourceTypeSavedPhotosAlbumUIImagePickerController*PickerImage = [[UIImagePickerController alloc]init];PickerImage.sourceType =UIImagePickerControllerSourceTypePhotoLibrary;//如果只是从相册中取图片或者视频,sourceType只能设置成UIImagePickerControllerSourceTypeSavedPhotosAlbum(展示出来的是具体图片或视频,如果只设置mediatype为视频,只有moments文件夹的内容能展示出来)或UIImagePickerControllerSourceTypePhotoLibrary(展示出来的是文件夹,有好几个文件夹moemnt,camera roll,videos,my photo stream)//PickerImage.mediaTypes=@[(NSString *)kUTTypeImage];//如果不设置mediaTypes,则默认是kUTTypeImage类型PickerImage.mediaTypes=@[(NSString *)kUTTypeMovie];//设置仅仅打开视频PickerImage.mediaTypes= [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];//设置打开所有的媒体类型,返回一个mediaType数组
//允许编辑,即放大裁剪PickerImage.allowsEditing =YES;//自代理
PickerImage.delegate =self;//页面跳转[self presentViewController:PickerImage animated:YES completion:nil];}
//用相机拍照或者录像
-(void)useCameraGetImageOrVideo:(NSInteger )index{
UIImagePickerController*PickerImage = [[UIImagePickerController alloc]init];/*获取方式:通过相机如果是打开相机拍照或者录像,sourceType只能设置成UIImagePickerControllerSourceTypeCamera*/PickerImage.sourceType =UIImagePickerControllerSourceTypeCamera;PickerImage.allowsEditing =YES;
PickerImage.delegate =self;
/*设置所支持的类型,设置只能拍照,或则只能录像,或者两者都可以(有选择的设置)
如果不设置mediatupes,默认情况下此数组只包含kUTTypeImage,表示拍照如果要录像,必须设置为kUTTypeVideo(视频不带声音)或kUTTypeMovie(视频带声音)*/NSString *requiredMediaType = (NSString *)kUTTypeImage;//拍照NSString *requiredMediaType1 = (NSString *)kUTTypeMovie;//录像NSArray*arrMediaTypes=[NSArray arrayWithObjects:requiredMediaType,requiredMediaType1,nil];if(index==0){//照相和录像arrMediaTypes=[NSArray arrayWithObjects:requiredMediaType,requiredMediaType1,nil];//设置录制视频的质量[PickerImage setVideoQuality:UIImagePickerControllerQualityTypeHigh];//设置最长摄像时间[PickerImage setVideoMaximumDuration:10.f];}else if(index==1){//照相arrMediaTypes=[NSArray arrayWithObjects:requiredMediaType,nil];}else if(index==2){//录像arrMediaTypes=[NSArray arrayWithObjects:requiredMediaType1,nil];/*设置摄像头捕捉模式,在这里设置了报错,(但是在自定义相机面时是有作用的,设置UIImagePickerControllerCameraCaptureModeVideo表示录像,UIImagePickerControllerCameraCaptureModePhoto表示拍照),但是MediaTypes必须设置*/
// PickerImage.cameraCaptureMode=UIImagePickerControllerCameraCaptureModeVideo;//设置录制视频的质量[PickerImage setVideoQuality:UIImagePickerControllerQualityTypeHigh];//设置最长摄像时间[PickerImage setVideoMaximumDuration:10.f];}[PickerImage setMediaTypes:arrMediaTypes];//设置媒体类型[self presentViewController:PickerImage animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString*,id> *)info
{if([info[UIImagePickerControllerMediaType] isEqualToString:(NSString *)kUTTypeImage]) {//拍照,或者选择相册走这里
//获取编辑后的图片
UIImage*Editedimage = info[UIImagePickerControllerEditedImage];//发通知,吧数据传给view,然后刷新collectionview[[NSNotificationCenter defaultCenter]postNotificationName:@"CmaraImage" object:nil userInfo:@{@"images":@[Editedimage]}];
//压缩图片
CGSize newSize=CGSizeMake(90, 90);UIGraphicsBeginImageContext(newSize);[Editedimage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();//从图形上下文获取新的图片UIGraphicsEndImageContext();//获得原图
// UIImage *Originalimage = info[UIImagePickerControllerOriginalImage];
//将照片保存到相册
// SEL是一个异步回调(参数是固定的否者会报错),不需要的话可以写nil,
UIImageWriteToSavedPhotosAlbum(Editedimage,self,@selector(imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:),nil);
// UIImageWriteToSavedPhotosAlbum(Editedimage, nil, nil, nil);}else if([info[UIImagePickerControllerMediaType] isEqualToString:(NSString *)kUTTypeMovie]){//录像// movie的路径
NSURL*url = info[UIImagePickerControllerMediaURL];// movie是否可以保存到相册
BOOL canbesaved =UIVideoAtPathIsCompatibleWithSavedPhotosAlbum([url path]);if (canbesaved) {//将movie保存到相
UISaveVideoAtPathToSavedPhotosAlbum(url.path,self,@selector(videoSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:),nil);}else{
NSLog(@"录像不能保存到相册");}
}else{
NSLog(@"%@",info[UIImagePickerControllerMediaType]);}[self dismissViewControllerAnimated:YES completion:nil];}- (void)image:(UIImage*)image didFinishSavingWithError:(NSError*)error contextInfo:(void *)contextInfo {NSLog(@"111");}
#pragma mark - 异步回调//保存照片到系统相册- (void)imageSavedToPhotosAlbum:(UIImage*)image didFinishSavingWithError:(NSError*)error contextInfo:(void *)contextInfo
{
if(!error) {NSLog(@"图片保存成功");}else{NSLog(@"图片保存不成功,error:%@",error);}}//保存录像到系统界面- (void)videoSavedToPhotosAlbum:(NSString*)videoPath didFinishSavingWithError:(NSError*)error contextInfo:(void *)contextInfo
{if(!error) {NSLog(@"视频保存成功");}else{NSLog(@"视频保存不成功,error:%@",error);}
}@end
*************************相册多选框架TZImagePickerController**************
github地址:https://github.com/banchichen/TZImagePickerController
/**TZImagePickerController相册多选框架(照片和和视频)可以单独使用,直接把这个分类导入即可使用:在选择完照片后挥发通知在外部接受通知[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(selectImagesNoti:) name:@"selectImage" object:nil];//通过TZImage选择照片的通知
-(void)selectImagesNoti:(NSNotification *)noti{NSDictionary *dict=noti.userInfo;if([[dict allKeys]containsObject:@"images"]){NSArray *images=dict[@"images"];}}*/#import <UIKit/UIKit.h>
#import "TZImagePickerController.h"
NS_ASSUME_NONNULL_BEGIN@interface UIViewController (TZIMagePickvc)<TZImagePickerControllerDelegate>
//@property(nonatomic,copy)void (^selectImageBlcok)(NSArray *images);
- (void)showPhotoPickerWithTag:(NSInteger) tag;
@endNS_ASSUME_NONNULL_END***********#import "UIViewController+TZIMagePickvc.h"
#import <objc/message.h>
// 属性名称
static const char * key = "name";//必须用char *,用NSString会报错
@implementation UIViewController (TZIMagePickvc)
- (void)showPhotoPickerWithTag:(NSInteger) tag {NSInteger maxCount = 9;//一次做多上传多少张TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:maxCount columnNumber:4 delegate:self];[imagePickerVc setSortAscendingByModificationDate:NO];imagePickerVc.allowTakePicture = YES; // 在内部显示拍照按钮imagePickerVc.naviBgColor = [UIColor whiteColor];imagePickerVc.naviTitleColor = [UIColor blackColor];imagePickerVc.barItemTextColor = [UIColor orangeColor];imagePickerVc.oKButtonTitleColorNormal = [UIColor orangeColor];imagePickerVc.oKButtonTitleColorDisabled = [UIColor lightGrayColor];imagePickerVc.statusBarStyle = UIStatusBarStyleDefault;// imagePickerVc.photoDefImageName = @"";imagePickerVc.photoSelImage = [UIImage imageNamed:@"comm_btn_checkmark"];imagePickerVc.photoNumberIconImage = [UIImage imageNamed:@""];imagePickerVc.photoOriginDefImage = [UIImage imageNamed:@""];imagePickerVc.photoOriginSelImage = [UIImage imageNamed:@""];// imagePickerVc.takePictureImageName = @"";imagePickerVc.allowPickingVideo = NO;imagePickerVc.allowPickingImage = YES;imagePickerVc.allowPickingOriginalPhoto = YES;imagePickerVc.allowPickingGif = NO;imagePickerVc.allowPickingMultipleVideo = NO; // 是否可以多选视频imagePickerVc.view.tag = tag;[self presentViewController:imagePickerVc animated:YES completion:nil];}
//选择录像
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(id)asset{// __weak typeof(self) weakSelf = self;PHAsset *ast = (PHAsset *)asset;PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];options.version = PHImageRequestOptionsVersionCurrent;options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;PHImageManager *manager = [PHImageManager defaultManager];[manager requestAVAssetForVideo:ast options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {AVURLAsset *urlAsset = (AVURLAsset *)asset;NSURL *url = urlAsset.URL;}];}
//选择图片后调用的代理
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray<UIImage *> *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto{for (UIImage * image in photos) {NSLog(@"000%lu",(unsigned long)photos.count);}//发通知,吧数据传给view,然后刷新collectionview[[NSNotificationCenter defaultCenter]postNotificationName:@"selectImage" object:nil userInfo:@{@"images":photos}];
}
//选择gif
- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingGifImage:(UIImage *)animatedImage sourceAssets:(id)asset{}
///**
// 动态添加block
// */
//-(void)setSelectImageBlcok:(void (^)(NSArray * _Nonnull))selectImageBlcok{
// objc_setAssociatedObject(self,key, selectImageBlcok, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
//}
//
//-(void (^)(NSArray * _Nonnull))selectImageBlcok{
// return objc_getAssociatedObject(self, key);
//}
@end
//选择相册
-(void)selectxiangce{QMWNWEAKSELF;TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:9 delegate:self];imagePickerVc.allowPickingImage=YES;imagePickerVc.allowPickingVideo=NO;imagePickerVc.allowTakePicture=YES;[imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {[weakSelf.imageArr addObjectsFromArray:photos];weakSelf.headerview.imageArr=weakSelf.imageArr;if(weakSelf.imageArr.count>0){SLog(@"--tupian%@",weakSelf.imageArr[0]);}
// [weakSelf requestkeyWIthimageorattach:@"1"];//图片PHImageRequestOptions *options=[[PHImageRequestOptions alloc]init];options.version=PHImageRequestOptionsVersionCurrent;options.deliveryMode=PHImageRequestOptionsDeliveryModeFastFormat;PHImageManager *manager = [PHImageManager defaultManager];
// if (@available(iOS 13, *)) {
// [manager requestImageDataAndOrientationForAsset:assets[0] options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, CGImagePropertyOrientation orientation, NSDictionary * _Nullable info) {
//
// }];
// } else {
// [manager requestImageForAsset:assets[0] targetSize:CGSizeMake(WIDTH, HEIGHT) contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
// SLog(@"tupian---%@",info);
// }];
// }[manager requestImageDataForAsset:assets[0] options:options resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {//获取imagedata数据}];//视频
// PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
// options.version = PHVideoRequestOptionsVersionCurrent;
// options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
// PHImageManager *manager = [PHImageManager defaultManager];
// [manager requestAVAssetForVideo:ast options:options resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
//
// AVURLAsset *urlAsset = (AVURLAsset *)asset;
//
// NSURL *url = urlAsset.URL;
//
//
// }];}];[self presentViewController:imagePickerVc animated:YES completion:nil];}
UIImagePickerController是继承UINavigationController,所以可以push和pop一些viewcontroller进行导航效果。例如,自定义照相机画面的时候可以在拍摄完后push一个viewcontroller用于对照片进行编辑。
相机常用属性:
//来源类型
@property(nonatomic) UIImagePickerControllerSourceType sourceType;
typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
UIImagePickerControllerSourceTypePhotoLibrary,默认全部相册
UIImagePickerControllerSourceTypeCamera,
UIImagePickerControllerSourceTypeSavedPhotosAlbum
} __TVOS_PROHIBITED;
//@property (nonatomic)NSTimeInterval videoMaximumDuration;//视频最大录制时长,默认10s@property (nonatomic)UIImagePickerControllerQualityType videoQuality;//视频质量typedefNS_ENUM(NSInteger,UIImagePickerControllerQualityType) { UIImagePickerControllerQualityTypeHigh = 0,//高清UIImagePickerControllerQualityTypeMedium,//中等,适合WiFi传输UIImagePickerControllerQualityTypeLow,//低质量,适合蜂窝网传输UIImagePickerControllerQualityType640x480,//640*480UIImagePickerControllerQualityTypeIFrame1280x720,//1280*720UIImagePickerControllerQualityTypeIFrame960x540,//960*540};
@property (nonatomic)BOOL showsCameraControls;/* 是否显示摄像头控制面板,默认为YES */
@property (nonatomic,strong)UIView *cameraOverlayView;/* 摄像头上覆盖的视图 */自定义相机界面(控制面板)
@property (nonatomic)CGAffineTransform cameraViewTransform;/* 摄像头形变 */
@property (nonatomic)UIImagePickerControllerCameraCaptureMode cameraCaptureMode;/* 摄像头捕捉模式 */
typedefNS_ENUM(NSInteger,UIImagePickerControllerCameraCaptureMode) { UIImagePickerControllerCameraCaptureModePhoto,//拍照模式
UIImagePickerControllerCameraCaptureModeVideo//视频录制模式};@property (nonatomic)UIImagePickerControllerCameraDevice cameraDevice;/* 摄像头设备 */typedefNS_ENUM(NSInteger,UIImagePickerControllerCameraDevice) { UIImagePickerControllerCameraDeviceRear,//前置摄像头UIImagePickerControllerCameraDeviceFront//后置摄像头};@property (nonatomic)UIImagePickerControllerCameraFlashMode cameraFlashMode;/* 闪光灯模式 */typedefNS_ENUM(NSInteger,UIImagePickerControllerCameraFlashMode) { UIImagePickerControllerCameraFlashModeOff = -1,//关闭闪光灯UIImagePickerControllerCameraFlashModeAuto = 0,//闪光灯自动,默认UIImagePickerControllerCameraFlashModeOn = 1//打开闪光灯};
//最长录像时间
@property(nonatomic) NSTimeInterval videoMaximumDurationNS_AVAILABLE_IOS(3_1);
//showsCameraControls用于指定拍照时下方的工具栏是否显示,取而代之的是allowEditing,表示拍完照片或者从相册选完照片后,是否跳转到编辑模式对图片裁剪,只有在showsCameraControls为YES时才有效果。
@property(nonatomic) BOOL showsCameraControls NS_AVAILABLE_IOS(3_1); //是否显示控制面板
@property(nonatomic) BOOL allowsEditing NS_AVAILABLE_IOS(3_1); //允许编辑裁剪
//mediaTypes用于设置相机支持的功能,拍照或者是视频,返回值类型可以是:默认情况下此数组包含kUTTypeImage,表示拍照 如果要录像,必须设置为kUTTypeVideo(视频不带声音)或kUTTypeMovie(视频带声音)
mediaTypes用于设置相机支持的功能,拍照或者是视频,返回值类型可以是:默认情况下此数组包含kUTTypeImage,表示拍照 如果要录像,必须设置为kUTTypeVideo(视频不带声音)或kUTTypeMovie(视频带声音)
/*在此处注意我们要将MobileCoreServices 框架添加到项目中,然后将其导入:#import <MobileCoreServices/MobileCoreServices.h> 。不然后出现错误使用未声明的标识符 'kUTTypeMovie'
@property(nonatomic,copy) NSArray<NSString *> *mediaTypes;
类方法:
//是否能获得某个资源类型,有三种:
UIImagePickerControllerSourceTypePhotoLibrary,
UIImagePickerControllerSourceTypeCamera,
UIImagePickerControllerSourceTypeSavedPhotosAlbum
+ (BOOL)isSourceTypeAvailable:(UIImagePickerControllerSourceType)sourceType; // returns YES if source is available (i.e. camera present)
//某种资源类型可获得的所有媒体类型的集合;集合中可以是kUTTypeImage(表示拍照)
kUTTypeVideo(视频不带声音)或kUTTypeMovie(视频带声音)中的一种或几种;
+ (nullableNSArray<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.
//摄像头可获得的捕捉模式的集合
+ (nullableNSArray<NSNumber *> *)availableCaptureModesForCameraDevice:(UIImagePickerControllerCameraDevice)cameraDeviceNS_AVAILABLE_IOS(4_0);// returns array of NSNumbers (UIImagePickerControllerCameraCaptureMode)
2. 常用对象方法:
- (void)takePicture;//拍照
- (BOOL)startVideoCapture;//开始录制视频
- (void)stopVideoCapture;//停止录制视频
3. 代理方法:
/* 媒体获取完成会调用 */- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info;
/* 取消获取会调用 */- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker;
4. 扩展函数,用于保存到相簿:
/* 保存图片到相簿 */voidUIImageWriteToSavedPhotosAlbum(
UIImage *image,//保存的图片UIImage
id completionTarget,//回调的执行者
SEL completionSelector,//回调方法
void *contextInfo//回调参数信息);
//上面一般保存图片的回调方法为:- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
/* 判断是否能保存视频到相簿 */BOOLUIVideoAtPathIsCompatibleWithSavedPhotosAlbum(NSString *videoPath);
/* 保存视频到相簿 */voidUISaveVideoAtPathToSavedPhotosAlbum(
NSString *videoPath, //保存的视频文件路径
id completionTarget, //回调的执行者
SEL completionSelector,//回调方法
void *contextInfo//回调参数信息);
//上面一般保存视频的回调方法为:- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo;
********************
******************************
#pragma mark 调用系统相册及拍照功能实现的代理方法并且上传到服务器的数据库
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{//从相册获取图片
UIImage * chosenImage = info[UIImagePickerControllerEditedImage];
UIImageView * picImageView = (UIImageView *)[self.viewviewWithTag:500];
picImageView.image = chosenImage;
NSData * imageData =UIImageJPEGRepresentation(chosenImage,0.9);
//将图片上传到服务器
// --------------------------------------------------------
AFHTTPRequestOperationManager * manager = [[AFHTTPRequestOperationManager alloc]initWithBaseURL:nil];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/html",@"text/javascript",@"text/json",nil];
NSString * urlString = [NSString stringWithFormat:@"%@appuser/modifyUserIcon",BASE_URL];
NSUserDefaults * userDefaults = [NSUserDefaultsstandardUserDefaults];
NSMutableDictionary * dict = [NSMutableDictionarydictionaryWithCapacity:1];
[dict setObject:[userDefaultsobjectForKey:@"user_id"]forKey:@"user_id"];//链接服务器接口的参数
[manager POST:urlString parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
//通过post请求上传用户头像图片,name和fileName传的参数需要跟后台协商,看后台要传的参数名
[formData appendPartWithFileData:imageData name:@"img" fileName:@"img.jpg" mimeType:@"image/jpeg"];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
//解析后台返回的结果,如果不做一下处理,打印结果可能是一些二进制流数据
NSError *error;
NSDictionary * imageDict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:&error];//从服务器得到的数据是字典
//上传成功后更新数据
self.personModel.adperurl = imageDict[@"adperurl"];//
NSLog(@"上传图片成功0---%@",imageDict);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"上传图片--失败 -%@",error);
}];
[picker dismissViewControllerAnimated:YEScompletion:^{
}];
}
///////////////UIImagePickerController实现举例一(最主要的)
#import "ViewController.h"
#import <MobileCoreServices/MobileCoreServices.h>
@interfaceViewController ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
@property(nonatomic,strong)UIImagePickerController *pickVC;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
}
-(void)touchCancel{
[self.pickVCstopVideoCapture];//停止录像
NSLog(@"cancel");
}
-(void)touchOk{
// [self.pickVC takePicture];//拍照,capturemodal设置成UIImagePickerControllerCameraCaptureModePhoto时,这个方法才起作用
[self.pickVCstartVideoCapture];//开始录像
NSLog(@"OK");
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//初始化UIImagePickerController
UIImagePickerController *PickerImage = [[UIImagePickerControlleralloc]init];
self.pickVC=PickerImage;
// UIImagePickerController *PickerImage = [[UIImagePickerController alloc]init];
//初始化提示框
UIAlertController *alert = [UIAlertControlleralertControllerWithTitle:nilmessage:nilpreferredStyle:UIAlertControllerStyleActionSheet];
--------------打开相册或者视频------------- //按钮:从相册选择,类型:UIAlertActionStyleDefault
[alert addAction:[UIAlertActionactionWithTitle:@"从相册选择打开图片或打开视频"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction *_Nonnull action) {
//获取方式1:通过相册(呈现全部相册,以文件夹形式展示),UIImagePickerControllerSourceTypePhotoLibrary
//获取方式2,通过相机,UIImagePickerControllerSourceTypeCamera只能拍照
//获取方法3,通过相册(呈现全部图片,打开文件夹展示文件夹里面的内容),UIImagePickerControllerSourceTypeSavedPhotosAlbum
PickerImage.sourceType =
UIImagePickerControllerSourceTypePhotoLibrary;//如果只是从相册中取图片或者视频,sourceType只能设置成UIImagePickerControllerSourceTypeSavedPhotosAlbum(展示出来的是具体图片或视频,如果只设置mediatype为视频,只有moments文件夹的内容能展示出来)或UIImagePickerControllerSourceTypePhotoLibrary(展示出来的是文件夹,有好几个文件夹moemnt,camera roll,videos,my photo stream)
//PickerImage.mediaTypes=@[(NSString *)kUTTypeImage];//如果不设置mediaTypes,则默认是kUTTypeImage类型
// PickerImage.mediaTypes=@[(NSString *)kUTTypeMovie];//设置仅仅打开视频,需要导入#import <MobileCoreServices/MobileCoreServices.h>才能设置这个类型
PickerImage.mediaTypes= [UIImagePickerController availableMediaTypesForSourceType:
UIImagePickerControllerSourceTypePhotoLibrary];//设置打开所有的媒体类型,返回一个mediaType数组
//允许编辑,即放大裁剪
PickerImage.allowsEditing =YES;
//自代理
PickerImage.delegate =self;
//页面跳转
[selfpresentViewController:PickerImageanimated:YEScompletion:nil];
}]];
--------------------打开相机------------ //按钮:拍照,类型:UIAlertActionStyleDefault
[alert addAction:[UIAlertActionactionWithTitle:@"打开相机拍照后者录像"style:UIAlertActionStyleDefaulthandler:^(UIAlertAction *_Nonnull action){
/**
其实和从相册选择一样,只是获取方式不同,前面是通过相册,而现在,我们要通过相机的方式
*/
//获取方式:通过相机
PickerImage.sourceType =UIImagePickerControllerSourceTypeCamera;//如果是打开相机拍照或者录像,sourceType只能设置成UIImagePickerControllerSourceTypeCamera
PickerImage.allowsEditing =YES;
PickerImage.delegate =self;
//设置所支持的类型,设置只能拍照,或则只能录像,或者两者都可以(有选择的设置)
//如果不设置mediatupes,默认情况下此数组只包含kUTTypeImage,表示拍照
//如果要录像,必须设置为kUTTypeVideo(视频不带声音)或kUTTypeMovie(视频带声音)
NSString *requiredMediaType = (NSString *)kUTTypeImage;
NSString *requiredMediaType1 = (NSString *)kUTTypeMovie;
NSArray *arrMediaTypes=[NSArray arrayWithObjects:requiredMediaType, requiredMediaType1,nil];
[PickerImage setMediaTypes:arrMediaTypes];//设置媒体类型
PickerImage.cameraCaptureMode=UIImagePickerControllerCameraCaptureModeVideo;//设置摄像头捕捉模式,在这里好象不设置页可以,(但是在自定义相机面时是有作用的,设置UIImagePickerControllerCameraCaptureModeVideo表示录像,UIImagePickerControllerCameraCaptureModePhoto表示拍照),但是MediaTypes必须设置
//设置录制视频的质量
[PickerImage setVideoQuality:UIImagePickerControllerQualityTypeHigh];
//设置最长摄像时间
[PickerImage setVideoMaximumDuration:10.f];
//******************
/---------------------/自定义的相机界面,注意:自定义相机界面的设置必须是在sourcetype设置成了UIImagePickerControllerSourceTypeCamera之后,否则会报错,提示:sourceType must be UIImagePickerControllerSourceTypeCamera
PickerImage.showsCameraControls =NO;------------吧系统相机按钮隐藏
UIToolbar * tool = [[UIToolbar alloc]initWithFrame:CGRectMake(0,self.view.frame.size.height - 40, self.view.frame.size.width,40)];
tool.barStyle =UIBarStyleBlackTranslucent;
tool.barTintColor = [UIColor greenColor];
UIBarButtonItem * cancel = [[UIBarButtonItem alloc]initWithTitle:@"取消"style:UIBarButtonItemStylePlain target:self action:@selector(touchCancel)];
cancel.width =self.view.frame.size.width/2;
UIBarButtonItem * ok = [[UIBarButtonItem alloc]initWithTitle:@"确定"style:UIBarButtonItemStylePlain target:self action:@selector(touchOk)];
ok.width =self.view.frame.size.width/2;
[tool setItems:@[cancel,ok]];
//把自定义的view添加到UIImagePickerController的layView上
PickerImage.cameraOverlayView = tool;------------替换系统的相机按钮
//****************
[self presentViewController:PickerImage animated:YES completion:nil];---------------弹出相机页面
}]];
//-----------取消按钮-------按钮:取消,类型:UIAlertActionStyleCancel
[alert addAction:[UIAlertActionactionWithTitle:@"取消"style:UIAlertActionStyleCancelhandler:nil]];
[self presentViewController:alert animated:YES completion:nil];------弹出选择按钮
}
/*在此处注意我们要将MobileCoreServices 框架添加到项目中,然后将其导入:#import <MobileCoreServices/MobileCoreServices.h> 。不然后出现错误使用未声明的标识符 'kUTTypeMovie'
//照片视频保存到相册--------------选择完照片或视频后调用的代理方法
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
if ([info[UIImagePickerControllerMediaType] isEqualToString:(NSString *)kUTTypeImage]) {//拍照
//获取编辑后的图片
UIImage *Editedimage = info[UIImagePickerControllerEditedImage];
//压缩图片
CGSize newSize=CGSizeMake(90, 90);
UIGraphicsBeginImageContext(newSize);
[Editedimage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();//从图形上下文获取新的图片
UIGraphicsEndImageContext();
//获得原图
// UIImage *Originalimage = info[UIImagePickerControllerOriginalImage];
//将照片保存到相册
// SEL是一个异步回调(参数是固定的否者会报错),不需要的话可以写nil,
UIImageWriteToSavedPhotosAlbum(Editedimage,self,@selector(imageSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:),nil);
// UIImageWriteToSavedPhotosAlbum(Editedimage, nil, nil, nil);
}elseif ([info[UIImagePickerControllerMediaType] isEqualToString:(NSString *)kUTTypeMovie]){//录像
// movie的路径
NSURL *url = info[UIImagePickerControllerMediaURL];
// movie是否可以保存到相册
BOOL canbesaved = UIVideoAtPathIsCompatibleWithSavedPhotosAlbum([urlpath]);
if (canbesaved) {
//将movie保存到相册
UISaveVideoAtPathToSavedPhotosAlbum(url.path,self,@selector(videoSavedToPhotosAlbum:didFinishSavingWithError:contextInfo:),nil);
}else{
NSLog(@"movie can not be saved to the Camera Roll album");
}
}else{
NSLog(@"%@",info[UIImagePickerControllerMediaType]);
}
[selfdismissViewControllerAnimated:YEScompletion:nil];
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(voidvoid *)contextInfo {
NSLog(@"111");
}
#pragma mark - 异步回调
//保存图到系统相册
- (void)imageSavedToPhotosAlbum:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (!error) {
NSLog(@"图片保存成功");
}else{
NSLog(@"图片保存不成功,error:%@",error);
}
}
//保存录像到系统界面
- (void)videoSavedToPhotosAlbum:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(voidvoid *)contextInfo
{
if (!error) {
NSLog(@"视频保存成功");
}else{
NSLog(@"视频保存不成功,error:%@",error);
}
}
//////////////////举例二++++++++++++++++++++++++++++++++
一,//自定义按钮实现打开相册
<UIActionSheetDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>协议
- (IBAction)pickerImage:(id)sender {
//打开相册或相机
UIImagePickerController *picker = [[UIImagePickerControlleralloc]init];
//设置照片源
//获取方式1:通过相册(呈现全部相册),UIImagePickerControllerSourceTypePhotoLibrary
//获取方式2,通过相机拍摄,UIImagePickerControllerSourceTypeCamera
//获取方法3,通过相册(呈现全部图片),UIImagePickerControllerSourceTypeSavedPhotosAlbum
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; |
//参数设置
picker.allowsEditing =YES;//允许编辑
//设置代理
picker.delegate =self;
//弹出控制器
[self.navigationController presentViewController:pickeranimated:YEScompletion:nil];
}
//选中了图片的代理方法
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
NSLog(@"%@",info);
UIImage *image = info[UIImagePickerControllerEditedImage];//获取图片
NSData *imageData =UIImageJPEGRepresentation(image,0.2);//对图像做了压缩,0.2是失真度
//dismiss控制器
[self dismissViewControllerAnimated:YES completion:nil];
}
//取消图片选择控制器的代理方法
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
============================
AVFoundation自定义拍照录像:
=======================
UIActionSheet实现打开图片:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
// 获取cell.tag
UITableViewCell *cell = [tableViewcellForRowAtIndexPath:indexPath];
NSInteger tag = cell.tag;
// 判断
if (tag == 2) {//不做任务操作
WCLog(@"不做任务操作");
return;
}
if(tag == 0){//选择照片
WCLog(@"选择照片");
UIActionSheet *sheet = [[UIActionSheetalloc]initWithTitle:@"请选择"delegate:selfcancelButtonTitle:@"取消"destructiveButtonTitle:@"照相"otherButtonTitles:@"相册",nil];
[sheet showInView:self.view];
}else{//跳到下一个控制器
WCLog(@"跳到下一个控制器");
[selfperformSegueWithIdentifier:@"EditVCardSegue"sender:cell];
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
//获取编辑个人信息的控制
id destVc = segue.destinationViewController;
if ([destVcisKindOfClass:[WCEditProfileViewControllerclass]]) {
WCEditProfileViewController *editVc = destVc;
editVc.cell = sender;
editVc.delegate =self;
}
}
#pragma mark actionsheet的代理
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex ==2){//取消
return;
}
UIImagePickerController *imagePicker = [[UIImagePickerControlleralloc]init];
// 设置代理
imagePicker.delegate =self;
// 设置允许编辑
imagePicker.allowsEditing =YES;
if (buttonIndex ==0) {//照相
imagePicker.sourceType =UIImagePickerControllerSourceTypeCamera;
}else{//相册
imagePicker.sourceType =UIImagePickerControllerSourceTypePhotoLibrary;
}
// 显示图片选择器
[self presentViewController:imagePickeranimated:YES completion:nil];
}
#pragma mark 图片选择器的代理
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
WCLog(@"%@",info);
// 获取图片 设置图片
UIImage *image = info[UIImagePickerControllerEditedImage];
self.haedView.image = image;
//隐藏当前模态窗口
[self dismissViewControllerAnimated:YEScompletion:nil];
// 更新到服务器
[self editProfileViewControllerDidSave];
}
//选中图片后打印出来的图片信息:
=====================================
二,视频压缩(原理是:以低质量的导出)
- (void)viewDidLoad {
[superviewDidLoad];
//从相册中选择视频出来
UIImagePickerController *picker = [[UIImagePickerControlleralloc]init];
//设置素材的来源
self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.picker = picker;
/*
UIImagePickerControllerSourceTypePhotoLibrary, 相片库
UIImagePickerControllerSourceTypeCamera, 相机
UIImagePickerControllerSourceTypeSavedPhotosAlbum相册
*/
NSLog(@"%@",[UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary]);
self.picker.delegate =self;
//设置多媒体类型(设置所有类型) 图片 音频视频
self.picker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypePhotoLibrary];//设置所有多媒体类型
}
//设置单个多媒体类型,
注意如果是录像必须设置,如果是拍照此步骤可以省略,因为mediaType默认包含kUTTypeImage(注意媒体类型定义在MobileCoreServices.framework中;
<strong>//imagePickerController.mediaTypes = [NSArray arrayWithObject:(NSString *)kUTTypeMovie];</strong>
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
// NSLog(@"%@",info);
// UIImage *image = info[UIImagePickerControllerOriginalImage];
// self.imageView.image = image;
[self.picker dismissViewControllerAnimated:YES completion:nil];
//获取视频的url
NSURL *url = info[UIImagePickerControllerMediaURL];
//视频压缩
//8M 200KB应用场景 对像素要求不高但是需要看到视频的场景
// 小视频 网络传输
//压缩原理: 就是以低质量的导出
AVAsset *asset = [AVAssetasset WithURL:url];
//参数1是素材对象 参数2压缩的质量
AVAssetExportSession *session = [[AVAssetExportSession alloc]initWithAsset:asset presetName:AVAssetExportPresetMediumQuality];
//建议 : AVAssetExportPresetHighestQuality 不压缩 AVAssetExportPresetLowQuality低质量
//AVAssetExportPresetMediumQuality中间
//路径 放在什么地方?
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)lastObject]stringByAppendingPathComponent:@"hello.m4v"];
//删除之前存在的文件 如果没有就设么都不做
[[NSFileManager defaultManager]removeItemAtPath:path error:nil];
session.outputURL = [NSURL fileURLWithPath:path];
//文件格式
// self.session = session;
NSLog(@"%@",session.supportedFileTypes);
session.outputFileType =AVFileTypeQuickTimeMovie;
// NSLog(@"%@",NSHomeDirectory());
//导出
[session exportAsynchronouslyWithCompletionHandler:^{
NSLog(@"导出完成!!!");
}];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[selfpresentViewController:self.pickeranimated:YEScompletion:nil];
}