一共有两种方法自定义相册
第一种是iOS9之后过期的
<</span>AssetsLibrary/AssetsLibrary.h>苹果原生框架
第二种是iOS8推出的
<</span>Photos/Photos.h> 苹果原生框架,功能更多,但是只支持iOS8之后的版本
一般推荐使用
<</span>Photos/Photos.h> ,因为现在版本快iOS10了,有些版本没有升级的用户已经可以抛弃了
1.
添加图片到【相机胶卷】
1
> UIImageWriteToSavedPhoto sAlbum函数
2
> AssetsLibrary框架
3
> Photos框架(推荐)
2.
拥有一个【自定义相册】
1
> AssetsLibrary框架
2
> Photos框架(推荐)
3.
将刚才添加到【相机胶卷】的图片,引用(添加)到【自定义相册】
1
> AssetsLibrary框架
2
> Photos框架(推荐)
One:
如果只需要将要将图片保存到系统的相册中,只需要下面两句代码就搞定了
#文档里已经说明这个方法是保存到用户的相机胶卷里面的
Adds the specified image to the user’s Camera Roll album.
- (
void
)saveBtns
{
//
UIImageWriteToSavedPhoto sAlbum
(
self
.imageView
.image
,
self
,
@selector
(image:didFinishSavingWithError :contextInfo:),
@"传什么下面就调用什么什么"
);
}
// 需要实现下面的方法,或者传入三个参数即可
- (
void
)image:(
UIImage
*)image didFinishSavingWithError :(
NSError
*)error contextInfo:(
void
*)contextInfo
{
if
(error) {
[SVProgressHUD showErrorWithStatus:
@"保存失败"
];
}
else
{
[SVProgressHUD showSuccessWithStatus:
@"保存成功"
];
}
}
#注意: @selector() 方法一定要传入三个参数,不然图片虽然保存进去了,但是会崩了
因为参数越界
实参个数 > 形参个数, 就会出现参数越界
-[
NSInvocation
setArgument:atIndex:]: index (
2
)
out
of bounds [-
1
,
1
] :
Two:
需要用到这个库
官方文档给出的提示
//自定相册的类
#import
static
NSString
*kGroupNameKey =
@"nameKey"
;
static
NSString
*kDefaultGroupName =
@"会跳舞的狮子"
;
- (ALAssetsLibrary *)library
{
if
(!_library) {
_library = [[ALAssetsLibrary alloc] init];
}
return
_library;
}
- (
NSString
*)groupName
{
//先从沙盒中取得名字
NSString
*groupName = [[
NSUserDefaults
standardUserDefaults] stringForKey:kGroupNameKey];
if
(groupName ==
nil
) {
//如果沙盒中取不到这个key(文件夹的名字)
groupName = kDefaultGroupName;
//储存名字到沙盒里面
[[
NSUserDefaults
standardUserDefaults] setObject:groupName forKey:kGroupNameKey];
//synchronize 立马将上面的key保存到沙盒里面
[[
NSUserDefaults
standardUserDefaults]synchronize];
}
return
groupName;
}
- (
IBAction
)clickSave:(
id
)sender {
//创建自定义相册
//获得文件夹的名字 (调用从沙盒里面取的这个方法)
__block
NSString
*groupName = [
self
groupName];
//self的弱引用
__weakSelf;
//图片库
__
weak
ALAssetsLibrary *weakLibrary =
self
.library
;
//创建自定义的相册
[weakLibrary addAssetsGroupAlbumWithN ame:groupName resultBlock:^(ALAssetsGroup *group) {
if
(group) {
//新创建的文件夹
//直接把图片添加到文件夹中
[weakSelf addImageToGroup:group];
}
else
{
//遍历相册中的每一个文件
[weakLibrary enumerateGroupsWithTypes :ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group,
BOOL
*stop) {
//取出文件夹的名称
NSString
*name = [group valueForProperty:ALAssetsGroupPropertyNam e];
if
([name isEqualToString:groupName]) {
//如果相等,那么就是自己创建的文件夹
//添加图片到文件夹中
[weakSelf addImageToGroup:group];
*stop =
YES
;
// 将图片添加到了文件夹中就停止遍历
}
else
if
([name isEqualToString:
@"Camera Roll"
])
{
//文件夹被用户强制删除了 (拼接一个空格,就是不同的文件夹的名字)
groupName = [groupName stringByAppendingString:
@" "
];
//储存新的名字
[[
NSUserDefaults
standardUserDefaults] setObject:groupName forKey:kGroupNameKey];
[[
NSUserDefaults
standardUserDefaults]synchronize];
//创建新的文件夹中
[weakLibrary addAssetsGroupAlbumWithN ame:groupName resultBlock:^(ALAssetsGroup *group) {
//添加图片到文件夹中
[weakSelf addImageToGroup:group];
} failureBlock:
nil
];
}
} failureBlock:
nil
];
}
} failureBlock:
nil
];
}
- (
void
)addImageToGroup:(ALAssetsGroup *)group
{
__
weak
ALAssetsLibrary *weakLibrary =
self
.library
;
//需要保存的图片
CGImageRef
image =
self
.imageView
.image
.CGImage
;
//添加图片到相机胶卷 (因为要先存到全部的相片里面. 在根据对应的assetURL)
[weakLibrary writeImageToSavedPhotosA lbum:image metadata:
nil
completionBlock:^(
NSURL
*assetURL,
NSError
*error) {
// asset就是一张照片
[weakLibrary assetForURL:assetURL resultBlock:^(ALAsset *asset) {
//将照片保存到自定的文件夹中
[group addAsset:asset];
[SVProgressHUD showSuccessWithStatus:
@"保存成功"
];
} failureBlock:
nil
];
}];
}
Three:
先简单的介绍下,然后再上代码
Photos框架须知
1.
PHAsset : 一个PHAsset对象代表一张图片或者一个视频文件
1
> 负责查询一堆的PHAsset对象
2.
PHAssetCollection : 一个PHAssetCollection对象代表一个相册
1
> 负责查询一堆的PHAssetCollection对象
3.
PHAssetChangeRequest
1
> 负责执行对PHAsset的【增删改】操作
2
> 这个类只能放在-[PHPhotoLibrary performChanges:completionHandler:] 或者 -[PHPhotoLibrary performChangesAndWait:error:]方法的block中使用
4.
PHAssetCollectionChangeR equest
1
> 负责执行对PHAssetCollection的【增删改】操作
2
> 这个类只能放在-[PHPhotoLibrary performChanges:completionHandler:] 或者 -[PHPhotoLibrary performChangesAndWait:error:]方法的block中使用
错误信息
This method can only be called from inside of -[PHPhotoLibrary performChanges:completionHandler:] or -[PHPhotoLibrary performChangesAndWait:error:]
解决防范
// Asynchronously 异步执行操作
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetChangeRequest creationRequestForAssetF romImage:self.imageView.image];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
JHLog(@
"保存完毕"
)
}];
// Synchronously 同步执行操作
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
[PHAssetChangeRequest creationRequestForAssetF romImage:self.imageView.image];
} error:&error];
// 这个方法只适合加载普通的plist文件,不能用来加载Info.plist
[NSDictionary dictionaryWithContentsOf File:[[NSBundle mainBundle] pathForResource:@
"Test"
ofType:@
"plist"
]];
安全提示按钮选择
// PHAuthorizationStatusNot Determined
// 用户还没有对当前App授权过(用户从未点击过Don't Allow或者OK按钮)
// PHAuthorizationStatusRes tricted
// 因为一些系统原因导致无法访问相册(比如家长控制)
// PHAuthorizationStatusDen ied
// 用户已经明显拒绝过当前App访问相片数据(用户已经点击过Don't Allow按钮)
// PHAuthorizationStatusAut horized
// 用户已经允许过当前App访问相片数据(用户已经点击过OK按钮)
# 只有遵守了NSFastEnumeration协议的对象才能使用for-in循环
封装好的代码,可以根据公司的需求进行修改
我创建新的相册的名字就是APP的名字,
// 获取软件的名字作为相册的标题NSStringtitle = [NSBundle mainBundle].infoDictionary[(NSString )kCFBundleNameKey];
定义专属相册
#import
// 在interface中写方法的声明,是为了点语法有智能提示
- (PHFetchResult *)createdAssets;
- (PHAssetCollection *)createdCollection;
- (PHFetchResult *)createdAssets
{
}
- (PHAssetCollection *)createdCollection
{
}
- (
void
)saveImageIntoAlbum
{
}
- (
IBAction
)save {