ios开发多选照片实现
#import "ViewController.h"
#import <Photos/Photos.h> @interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate>
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
} - (IBAction)selectImage {
[self getThumbnailImages];
} /**
* 获得所有相簿的原图
*/
- (void)getOriginalImages
{
// 获得所有的自定义相簿
PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
// 遍历所有的自定义相簿
for (PHAssetCollection *assetCollection in assetCollections) {
[self enumerateAssetsInAssetCollection:assetCollection original:YES];
} // 获得相机胶卷
PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
[self enumerateAssetsInAssetCollection:cameraRoll original:YES];
} /**
* 获得所有相簿中的缩略图
*/
- (void)getThumbnailImages
{
// 获得所有的自定义相簿
PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
// 遍历所有的自定义相簿
for (PHAssetCollection *assetCollection in assetCollections) {
[self enumerateAssetsInAssetCollection:assetCollection original:NO];
} // 获得相机胶卷
PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
[self enumerateAssetsInAssetCollection:cameraRoll original:NO];
} /**
* 遍历相簿中的所有图片
*
* @param assetCollection 相簿
* @param original 是否要原图
*/
- (void)enumerateAssetsInAssetCollection:(PHAssetCollection *)assetCollection original:(BOOL)original
{
NSLog(@"相簿名:%@", assetCollection.localizedTitle); PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步获得图片, 只会返回1张图片
options.synchronous = YES; // 获得某个相簿中的所有PHAsset对象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
for (PHAsset *asset in assets) {
// 是否要原图
CGSize size = original ? CGSizeMake(asset.pixelWidth, asset.pixelHeight) : CGSizeZero; // 从asset中获得图片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"%@", result);
}];
}
} /**
* 获得相机胶卷中的所有图片
*/
- (void)getImagesFromCameraRoll
{
// 获得相机胶卷中的所有图片
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsWithOptions:nil]; __block int count = ; for (PHAsset *asset in assets) {
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(asset.pixelWidth, asset.pixelHeight) contentMode:PHImageContentModeDefault options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"%@ - %zd", result, count++);
}];
}
} /**
* 利用UIImagePickerController挑选图片
*/
- (void)getImageFromIpc
{
// UIImagePickerController : 可以从系统自带的App(照片\相机)中获得图片 // 判断相册是否可以打开
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return; UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
// 打开照片应用(显示所有相簿)
ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
// 打开照片应用(只显示"时刻"这个相簿)
// ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
// 照相机
// ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
ipc.delegate = self;
[self presentViewController:ipc animated:YES completion:nil];
} #pragma mark - <UIImagePickerControllerDelegate>
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
// 销毁控制器
[picker dismissViewControllerAnimated:YES completion:nil]; // 设置图片
self.imageView.image = info[UIImagePickerControllerOriginalImage];
} @end
总结:1:从相册中选取照片可以利用UIImagePickerController,前提是必须遵守两个协议:
<UIImagePickerControllerDelegate, UINavigationControllerDelegate>但是此种方法只能获取到相册中的一张照片。使用方法如下:1:可以先判断其是否支持相机或是相册,不支持直接return,不执行以下代码 2:创建对象,设置代理,在设置sourceType(注意两种类型的区别),弹出就用presentViewController可以弹出相册,dissmiss返回到应用。实现代理方法获取图片: self.imageView.image = info[UIImagePickerControllerOriginalImage];3:UIImagePickerController显示中文界面:
1.Project-->Info-->Localizations添加Chinese
2.修改Target-->Info-->Localization native development region : China
- (void)getImageFromIpc
{
// UIImagePickerController : 可以从系统自带的App(照片\相机)中获得图片
// 判断相册是否可以打开
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return;
UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
// 打开照片应用(显示所有相簿)
ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
// 打开照片应用(只显示"时刻"这个相簿)
// ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
// 照相机
// ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
ipc.delegate = self;
[self presentViewController:ipc animated:YES completion:nil];
}
#pragma mark - <UIImagePickerControllerDelegate>
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
// 销毁控制器
[picker dismissViewControllerAnimated:YES completion:nil];
// 设置图片
self.imageView.image = info[UIImagePickerControllerOriginalImage];
}
2:若是想多选照片:1:可用系统框架:#import <Photos/Photos.h> 2:使用步骤:1:先获得所有相簿,在获得相簿胶卷
PHAssetCollection
2:遍历相簿数组,得到每一个相册照片PHAsset,再利用PHAsset请求获得每一张照片
3:若想做成系统相簿的样式:1:此界面可采用九宫格搭建,或是采用collection搭建,建议用后者,因为后者可以有循环利用的机制,节省
内存
2:如下界面搭建:可以监听每张图片的点击,当点击到某张图片的时候,将封装好的蒙板和对勾,盖在上面,或是再移除
3:
## 获得自定义的所有相簿
```objc
// 获得所有的自定义相簿
PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
// 遍历所有的自定义相簿
for (PHAssetCollection *assetCollection in assetCollections) { }
``` ## 获得相机胶卷相簿
```objc
// 获得相机胶卷
PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject;
``` ## 获得某个相簿的缩略图
```objc
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步获得图片, 只会返回1张图片
options.synchronous = YES; // 获得某个相簿中的所有PHAsset对象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
for (PHAsset *asset in assets) {
CGSize size = CGSizeZero; // 从asset中获得图片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"%@", result);
}];
}
``` ## 获得某个相簿的原图
```objc
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
// 同步获得图片, 只会返回1张图片
options.synchronous = YES; // 获得某个相簿中的所有PHAsset对象
PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil];
for (PHAsset *asset in assets) {
CGSize size = CGSizeMake(asset.pixelWidth, asset.pixelHeight); // 从asset中获得图片
[[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
NSLog(@"%@", result);
}];
}
``` ## 利用UIImagePickerController挑选图片
```objc
// UIImagePickerController : 可以从系统自带的App(照片\相机)中获得图片 // 判断相册是否可以打开
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return; UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
// 打开照片应用(显示所有相簿)
ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
// 打开照片应用(只显示"时刻"这个相簿)
// ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
// 照相机
// ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
ipc.delegate = self;
[self presentViewController:ipc animated:YES completion:nil]; #pragma mark - <UIImagePickerControllerDelegate>
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info
{
// 销毁控制器
[picker dismissViewControllerAnimated:YES completion:nil]; // 设置图片
self.imageView.image = info[UIImagePickerControllerOriginalImage];
}
``` ## NaN错误
- 错误起因:0被当做除数, 比如 / ## 最简单的方法保存图片到相机胶卷
```objc
UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); /**
* 通过UIImageWriteToSavedPhotosAlbum函数写入图片完毕后就会调用这个方法
*
* @param image 写入的图片
* @param error 错误信息
* @param contextInfo UIImageWriteToSavedPhotosAlbum函数的最后一个参数
*/
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (error) {
[SVProgressHUD showErrorWithStatus:@"图片保存失败!"];
} else {
[SVProgressHUD showSuccessWithStatus:@"图片保存成功!"];
}
}
``` ## 保存图片到自定义相册
```objc
- (IBAction)save {
/*
PHAuthorizationStatusNotDetermined, 用户还没有做出选择
PHAuthorizationStatusDenied, 用户拒绝当前应用访问相册(用户当初点击了"不允许")
PHAuthorizationStatusAuthorized 用户允许当前应用访问相册(用户当初点击了"好")
PHAuthorizationStatusRestricted, 因为家长控制, 导致应用无法方法相册(跟用户的选择没有关系)
*/ // 判断授权状态
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
if (status == PHAuthorizationStatusRestricted) { // 因为家长控制, 导致应用无法方法相册(跟用户的选择没有关系)
[SVProgressHUD showErrorWithStatus:@"因为系统原因, 无法访问相册"];
} else if (status == PHAuthorizationStatusDenied) { // 用户拒绝当前应用访问相册(用户当初点击了"不允许")
XMGLog(@"提醒用户去[设置-隐私-照片-xxx]打开访问开关");
} else if (status == PHAuthorizationStatusAuthorized) { // 用户允许当前应用访问相册(用户当初点击了"好")
[self saveImage];
} else if (status == PHAuthorizationStatusNotDetermined) { // 用户还没有做出选择
// 弹框请求用户授权
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status == PHAuthorizationStatusAuthorized) { // 用户点击了好
[self saveImage];
}
}];
}
} - (void)saveImage
{
// PHAsset : 一个资源, 比如一张图片\一段视频
// PHAssetCollection : 一个相簿 // PHAsset的标识, 利用这个标识可以找到对应的PHAsset对象(图片对象)
__block NSString *assetLocalIdentifier = nil; // 如果想对"相册"进行修改(增删改), 那么修改代码必须放在[PHPhotoLibrary sharedPhotoLibrary]的performChanges方法的block中
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
// 1.保存图片A到"相机胶卷"中
// 创建图片的请求
assetLocalIdentifier = [PHAssetCreationRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedAsset.localIdentifier;
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success == NO) {
[self showError:@"保存图片失败!"];
return;
} // 2.获得相簿
PHAssetCollection *createdAssetCollection = [self createdAssetCollection];
if (createdAssetCollection == nil) {
[self showError:@"创建相簿失败!"];
return;
} [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
// 3.添加"相机胶卷"中的图片A到"相簿"D中 // 获得图片
PHAsset *asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetLocalIdentifier] options:nil].lastObject; // 添加图片到相簿中的请求
PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection]; // 添加图片到相簿
[request addAssets:@[asset]];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success == NO) {
[self showError:@"保存图片失败!"];;
} else {
[self showSuccess:@"保存图片成功!"];;
}
}];
}];
} /**
* 获得相簿
*/
- (PHAssetCollection *)createdAssetCollection
{
// 从已存在相簿中查找这个应用对应的相簿
PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *assetCollection in assetCollections) {
if ([assetCollection.localizedTitle isEqualToString:XMGAssetCollectionTitle]) {
return assetCollection;
}
} // 没有找到对应的相簿, 得创建新的相簿 // 错误信息
NSError *error = nil; // PHAssetCollection的标识, 利用这个标识可以找到对应的PHAssetCollection对象(相簿对象)
__block NSString *assetCollectionLocalIdentifier = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
// 创建相簿的请求
assetCollectionLocalIdentifier = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:XMGAssetCollectionTitle].placeholderForCreatedAssetCollection.localIdentifier;
} error:&error]; // 如果有错误信息
if (error) return nil; // 获得刚才创建的相簿
return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[assetCollectionLocalIdentifier] options:nil].lastObject;
} - (void)showSuccess:(NSString *)text
{
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showSuccessWithStatus:text];
});
} - (void)showError:(NSString *)text
{
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD showErrorWithStatus:text];
});
}
``` ## Xcode插件的安装路径
```objc
/Users/用户名/Library/Application Support/Developer/Shared/Xcode/Plug-ins
```
ios开发多选照片实现的更多相关文章
- iOS:iOS开发非常全的三方库、插件等等
iOS开发非常全的三方库.插件等等 github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自git ...
- iOS开发之资料收集
github排名:https://github.com/trending, github搜索:https://github.com/search. 此文章转自github:https://github ...
- iOS开发 非常全的三方库、插件、大牛博客等等
UI 下拉刷新 EGOTableViewPullRefresh- 最早的下拉刷新控件. SVPullToRefresh- 下拉刷新控件. MJRefresh- 仅需一行代码就可以为UITableVie ...
- iOS开发系列--Swift语言
概述 Swift是苹果2014年推出的全新的编程语言,它继承了C语言.ObjC的特性,且克服了C语言的兼容性问题.Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在 ...
- iOS开发系列--打造自己的“美图秀秀”
--绘图与滤镜全面解析 概述 在iOS中可以很容易的开发出绚丽的界面效果,一方面得益于成功系统的设计,另一方面得益于它强大的开发框架.今天我们将围绕iOS中两大图形.图像绘图框架进行介绍:Quartz ...
- iOS开发之再探多线程编程:Grand Central Dispatch详解
Swift3.0相关代码已在github上更新.之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread.操作队列以及GCD,介绍的不够深入.今天就以GCD为主题来全面的总结一下GCD ...
- 总结iOS开发中的断点续传那些事儿
前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...
- iOS开发系列文章(持续更新……)
iOS开发系列的文章,内容循序渐进,包含C语言.ObjC.iOS开发以及日后要写的游戏开发和Swift编程几部分内容.文章会持续更新,希望大家多多关注,如果文章对你有帮助请点赞支持,多谢! 为了方便大 ...
- iOS开发系列--App扩展开发
概述 从iOS 8 开始Apple引入了扩展(Extension)用于增强系统应用服务和应用之间的交互.它的出现让自定义键盘.系统分享集成等这些依靠系统服务的开发变成了可能.WWDC 2016上众多更 ...
随机推荐
- CISP/CISA 每日一题 17
CISSP 每日一题(答) What are often added to passwords to maketheir resultant hash secure and resistant to ...
- Eclipse中Git插件使用技巧:[5]还原文件
如果修改了某个文件并未提交至本地库(add index),那么怎么还原呢?Git插件中并不像Svn插件直接提供有还原方式.其实无论是否提交至本地库或者远程库,还原操作的本质都是将文件的当前版本还原至之 ...
- COGS——T 1265. [NOIP2012] 同余方程
http://cogs.pro/cogs/problem/problem.php?pid=1265 ★☆ 输入文件:mod.in 输出文件:mod.out 简单对比时间限制:1 s 内 ...
- Light OJ 1373 Strongly Connected Chemicals 二分匹配最大独立集
m种阳离子 n种阴离子 然后一个m*n的矩阵 第i行第j列为1代表第i种阴离子和第j种阴离子相互吸引 0表示排斥 求在阳离子和阴离子都至少有一种的情况下 最多存在多少种离子能够共存 阴阳离子都至少须要 ...
- web service 原理
Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的 ...
- IOS的UIWebView中JS点击事件,需要加入cursor:pointer;属性才可以
IOS的UIWebView中JS点击事件,需要加入cursor:pointer;属性才可以. Android的WebView可以支持外链样式,js文件:IOS则需要改为内嵌样式和JS文件.
- 绝对定位等html结构,水平居中的处理方案
1.父子结构,父relative,子absolute.子元素要水平居中:left:50%:margin-left:子元素一半的宽度.因为定位的left是按左边框开始计算.[固定问题的模块化解决]
- 原生js大总结七
061.如何获取父级节点.上一个子级节点.下一个子级节点 nextElementSibling 后一个兄弟元素 (如果没有是null) previousElementSibling ...
- 【例题 7-8 UVA - 10603】Fill
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 三维显然可以缩短为2维. 只要知道a,b瓶中的水量,c瓶中的水量减一下就能得到. 则设dis[a][b]表示a,b瓶中水量为a,b时 ...
- Redo current损坏
如果损坏的是current redo log (select group#,sequence#,archived,status from v$log;) 有两种情况: A. 数据库是正常关闭 ...