1 ## 获得自定义的所有相簿 2 3 // 获得所有的自定义相簿 4 PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil]; 5 // 遍历所有的自定义相簿 6 for (PHAssetCollection *assetCollection in assetCollections) { 7 8 } 9 10 11 ## 获得相机胶卷相簿 12 13 // 获得相机胶卷 14 PHAssetCollection *cameraRoll = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary options:nil].lastObject; 15 16 17 ## 获得某个相簿的缩略图 18 19 PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; 20 // 同步获得图片, 只会返回1张图片 21 options.synchronous = YES; 22 23 // 获得某个相簿中的所有PHAsset对象 24 PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil]; 25 for (PHAsset *asset in assets) { 26 CGSize size = CGSizeZero; 27 28 // 从asset中获得图片 29 [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { 30 NSLog(@"%@", result); 31 }]; 32 } 33 34 35 ## 获得某个相簿的原图 36 37 PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; 38 // 同步获得图片, 只会返回1张图片 39 options.synchronous = YES; 40 41 // 获得某个相簿中的所有PHAsset对象 42 PHFetchResult<PHAsset *> *assets = [PHAsset fetchAssetsInAssetCollection:assetCollection options:nil]; 43 for (PHAsset *asset in assets) { 44 CGSize size = CGSizeMake(asset.pixelWidth, asset.pixelHeight); 45 46 // 从asset中获得图片 47 [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:size contentMode:PHImageContentModeDefault options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { 48 NSLog(@"%@", result); 49 }]; 50 } 51 52 53 ## 利用UIImagePickerController挑选图片 54 55 // UIImagePickerController : 可以从系统自带的App(照片相机)中获得图片 56 57 // 判断相册是否可以打开 58 if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) return; 59 60 UIImagePickerController *ipc = [[UIImagePickerController alloc] init]; 61 // 打开照片应用(显示所有相簿) 62 ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; 63 // 打开照片应用(只显示"时刻"这个相簿) 64 // ipc.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; 65 // 照相机 66 // ipc.sourceType = UIImagePickerControllerSourceTypeCamera; 67 ipc.delegate = self; 68 [self presentViewController:ipc animated:YES completion:nil]; 69 70 #pragma mark - <UIImagePickerControllerDelegate> 71 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info 72 { 73 // 销毁控制器 74 [picker dismissViewControllerAnimated:YES completion:nil]; 75 76 // 设置图片 77 self.imageView.image = info[UIImagePickerControllerOriginalImage]; 78 } 79 80 81 ## NaN错误 82 - 错误起因:0被当做除数, 比如 10 / 0 83 84 ## 最简单的方法保存图片到相机胶卷 85 86 UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); 87 88 /** 89 * 通过UIImageWriteToSavedPhotosAlbum函数写入图片完毕后就会调用这个方法 90 * 91 * @param image 写入的图片 92 * @param error 错误信息 93 * @param contextInfo UIImageWriteToSavedPhotosAlbum函数的最后一个参数 94 */ 95 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo 96 { 97 if (error) { 98 [SVProgressHUD showErrorWithStatus:@"图片保存失败!"]; 99 } else { 100 [SVProgressHUD showSuccessWithStatus:@"图片保存成功!"]; 101 } 102 } 103 104 105 ## 保存图片到自定义相册 106 107 - (IBAction)save { 108 /* 109 PHAuthorizationStatusNotDetermined, 用户还没有做出选择 110 PHAuthorizationStatusDenied, 用户拒绝当前应用访问相册(用户当初点击了"不允许") 111 PHAuthorizationStatusAuthorized 用户允许当前应用访问相册(用户当初点击了"好") 112 PHAuthorizationStatusRestricted, 因为家长控制, 导致应用无法方法相册(跟用户的选择没有关系) 113 */ 114 115 // 判断授权状态 116 PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus]; 117 if (status == PHAuthorizationStatusRestricted) { // 因为家长控制, 导致应用无法方法相册(跟用户的选择没有关系) 118 [SVProgressHUD showErrorWithStatus:@"因为系统原因, 无法访问相册"]; 119 } else if (status == PHAuthorizationStatusDenied) { // 用户拒绝当前应用访问相册(用户当初点击了"不允许") 120 MKLog(@"提醒用户去[设置-隐私-照片-xxx]打开访问开关"); 121 } else if (status == PHAuthorizationStatusAuthorized) { // 用户允许当前应用访问相册(用户当初点击了"好") 122 [self saveImage]; 123 } else if (status == PHAuthorizationStatusNotDetermined) { // 用户还没有做出选择 124 // 弹框请求用户授权 125 [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { 126 if (status == PHAuthorizationStatusAuthorized) { // 用户点击了好 127 [self saveImage]; 128 } 129 }]; 130 } 131 } 132 133 - (void)saveImage 134 { 135 // PHAsset : 一个资源, 比如一张图片一段视频 136 // PHAssetCollection : 一个相簿 137 138 // PHAsset的标识, 利用这个标识可以找到对应的PHAsset对象(图片对象) 139 __block NSString *assetLocalIdentifier = nil; 140 141 // 如果想对"相册"进行修改(增删改), 那么修改代码必须放在[PHPhotoLibrary sharedPhotoLibrary]的performChanges方法的block中 142 [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 143 // 1.保存图片A到"相机胶卷"中 144 // 创建图片的请求 145 assetLocalIdentifier = [PHAssetCreationRequest creationRequestForAssetFromImage:self.imageView.image].placeholderForCreatedAsset.localIdentifier; 146 } completionHandler:^(BOOL success, NSError * _Nullable error) { 147 if (success == NO) { 148 [self showError:@"保存图片失败!"]; 149 return; 150 } 151 152 // 2.获得相簿 153 PHAssetCollection *createdAssetCollection = [self createdAssetCollection]; 154 if (createdAssetCollection == nil) { 155 [self showError:@"创建相簿失败!"]; 156 return; 157 } 158 159 [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 160 // 3.添加"相机胶卷"中的图片A到"相簿"D中 161 162 // 获得图片 163 PHAsset *asset = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetLocalIdentifier] options:nil].lastObject; 164 165 // 添加图片到相簿中的请求 166 PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:createdAssetCollection]; 167 168 // 添加图片到相簿 169 [request addAssets:@[asset]]; 170 } completionHandler:^(BOOL success, NSError * _Nullable error) { 171 if (success == NO) { 172 [self showError:@"保存图片失败!"];; 173 } else { 174 [self showSuccess:@"保存图片成功!"];; 175 } 176 }]; 177 }]; 178 } 179 180 /** 181 * 获得相簿 182 */ 183 - (PHAssetCollection *)createdAssetCollection 184 { 185 // 从已存在相簿中查找这个应用对应的相簿 186 PHFetchResult<PHAssetCollection *> *assetCollections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil]; 187 for (PHAssetCollection *assetCollection in assetCollections) { 188 if ([assetCollection.localizedTitle isEqualToString:XMGAssetCollectionTitle]) { 189 return assetCollection; 190 } 191 } 192 193 // 没有找到对应的相簿, 得创建新的相簿 194 195 // 错误信息 196 NSError *error = nil; 197 198 // PHAssetCollection的标识, 利用这个标识可以找到对应的PHAssetCollection对象(相簿对象) 199 __block NSString *assetCollectionLocalIdentifier = nil; 200 [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{ 201 // 创建相簿的请求 202 assetCollectionLocalIdentifier = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:XMGAssetCollectionTitle].placeholderForCreatedAssetCollection.localIdentifier; 203 } error:&error]; 204 205 // 如果有错误信息 206 if (error) return nil; 207 208 // 获得刚才创建的相簿 209 return [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[assetCollectionLocalIdentifier] options:nil].lastObject; 210 } 211 212 - (void)showSuccess:(NSString *)text 213 { 214 dispatch_async(dispatch_get_main_queue(), ^{ 215 [SVProgressHUD showSuccessWithStatus:text]; 216 }); 217 } 218 219 - (void)showError:(NSString *)text 220 { 221 dispatch_async(dispatch_get_main_queue(), ^{ 222 [SVProgressHUD showErrorWithStatus:text]; 223 }); 224 } 225 226 227 ## Xcode插件的安装路径 228 229 /Users/用户名/Library/Application Support/Developer/Shared/Xcode/Plug-ins