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上众多更 ...
随机推荐
- node:json与csv互转
[单个文件的转化] 1.安装json2csv模块将json转成csv jsonToCSV.js var fs = require('fs'); const Json2csvParser = r ...
- (转)Linux下查看Nginx Apache MySQL的并发连接数和连接状态
转自: http://www.ha97.com/4106.html 1.查看Web服务器(Nginx Apache)的并发请求数及其TCP连接状态:netstat -n | awk '/^tcp/ { ...
- 通过no-gui模式运行jmeter脚本与生成报告
说明:使用NO-GUI 模式,即命令行模式运行 JMeter 测试脚本能够大大缩减所需要的系统资源. 步骤:在GUI(图形化界面)模式调整好脚本,通过FTP工具将需要测试的.jmx文件传输到linux ...
- 【习题 7-4 UVA-818】Cutting Chains
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 二进制枚举要解开哪些环. 把所有和它相关的边都删掉. 对于剩下的联通分量. 看看是不是每一个联通分量都是一条链 ->每个点的度 ...
- 循环体(for/while)循环变量的设置
1. 求滑动(移动)平均(moving average) double partialSum = 0; for (int i = 0; i < M-1; ++i) partialSum += A ...
- 使用Spring框架的好处
转自:https://www.cnblogs.com/hoobey/p/6032506.html 在SSH框假中spring充当了管理容器的角色.我们都知道Hibernate用来做持久层,因为它将JD ...
- 10.static_extern
另一个文件声明 #include <iostream> using namespace std; ; void show() { cout << " << ...
- 【例题 7-1 UVA - 725】Division
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 枚举分母从0到99999. 得到分子,判断合法 [代码] /* 1.Shoud it use long long ? 2.Have ...
- Java Web学习总结(8)——使用Cookie进行会话管理
一.会话的概念 会话可简单理解为:用户开一个浏览器,点击多个超链接,访问服务器多个web资源,然后关闭浏览器,整个过程称之为一个会话. 有状态会话:一个同学来过教室,下次再来教室,我们会知道这个同学曾 ...
- Hypervisor, computer system, and virtual processor scheduling method
A hypervisor calculates the total number of processor cycles (the number of processor cycles of one ...