开发步骤
- 给UIImageView添加一个点击手势,点击弹出图片控制器
- 图片控制器中的子视图包括UIScrollView、一个返回按钮、一个保存按钮
- 保存图片到【相机胶卷】中
- C语言函数:UIImageWriteToSavedPhotosAlbum
- AssetsLibrary框架
- Photos框架
- 自定义一个相册,相册名字一般为应用的名称
- AssetsLibrary框架
- Photos框架
- 将【相机胶卷】中的保存的图片的引用添加到【自定义相册】中
- AssetsLibrary框架
- Photos框架
具体开发步骤
- (void)saveClick {
// 获取授权状态
PHAuthorizationStatus oldStatus = [PHPhotoLibrary authorizationStatus];
// 如果用户还没有做出选择,该方法会弹出授权,如果用户做出了选择就执行代码块中的代码
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
dispatch_async(dispatch_get_main_queue(), ^{
if (status == PHAuthorizationStatusDenied) {
//
if (oldStatus != PHAuthorizationStatusNotDetermined) {
[SVProgressHUD showWithStatus:@"打开开关"];
}
} else if (status == PHAuthorizationStatusAuthorized) {
[self savePhotoToAppAlbum];
} else if (status == PHAuthorizationStatusRestricted) {
[SVProgressHUD showErrorWithStatus:@"因系统原因,无法访问相册!"];
}
});
}];
}
// 保存图片到自定义的App相册中
- (void)savePhotoToAppAlbum {
// 1. 将图片保存到[相机胶卷]相册中
PHFetchResult<PHAsset *> *createdAssets = [self createAssets];
if (createdAssets == nil) {
[SVProgressHUD showErrorWithStatus:@"保存图片失败"];
return;
}
// 2. 创建自定义相册
PHAssetCollection *createdCollection = [self createCollection];
if (createdCollection == nil) {
[SVProgressHUD showErrorWithStatus:@"创建相册失败"];
return;
}
// 3. 将图片添加到自定义的相册中
NSError *error = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdCollection];
[request insertAssets:createdAssets atIndexes:[NSIndexSet indexSetWithIndex:0]];
} error:&error];
if (error == nil) {
[SVProgressHUD showSuccessWithStatus:@"保存成功!"];
} else {
[SVProgressHUD showErrorWithStatus:@"保存失败!"];
}
}
// 保存相册到【相机胶卷】中,并返回保存的图片
- (PHFetchResult<PHAsset *> *)createAssets {
NSError *error = nil;
__block NSString *assetID = nil;
// 保存相册到【相机胶卷】中
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
assetID = [PHAssetChangeRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedAsset.localIdentifier;
} error:&error];
if (error != nil) return nil;
return [PHAsset fetchAssetsWithLocalIdentifiers:@[assetID] options:nil];
}
// 创建相册
- (PHAssetCollection *)createCollection {
// 相册标题
NSString *title = [NSBundle mainBundle].infoDictionary[(__bridge NSString *)kCFBundleNameKey];
// 判断是否已经创建过该相册,创建则返回,否则创建新的相册
PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
for (PHAssetCollection *collection in collections) {
if ([collection.localIdentifier isEqualToString:title]) {
return collection;
}
}
NSError *error = nil;
__block NSString *createdCollectionID = nil;
[[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
createdCollectionID = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title].placeholderForCreatedAssetCollection.localIdentifier;
} error:&error];
if (error != nil) return nil;
return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createdCollectionID] options:nil].firstObject;
}
其他知识点
weak使用__weak修饰: 当对象销毁后,对象的值指向nil指针,不会报错,更加安全,容错性更强
assign使用__unsafe_unretained:当对象销毁后,对象的值仍然指向原来的指针,访问时EXE_BAD_ACCESS(访问野指针)
初始化子控件方式一:
一般在viewDidLoad中初始化子控件
一般在viewDidLayoutSubviews(视图已经布局完子视图)布局子视图的位置和尺寸
初始化子控件方式二:
使用懒加载中初始化子控件
一般在viewDidLayoutSubviews(视图已经布局完子视图)布局子视图的位置和尺寸