保存照片是一件极其恶心的事!下面介绍一下照片的存和取
iOS 10推出了访问权限,在plist里添加即可
<!-- 相册 -->
<key>NSPhotoLibraryUsageDescription</key>
<string>App需要您的同意,才能访问相册</string>
<!-- 相机 -->
<key>NSCameraUsageDescription</key>
<string>App需要您的同意,才能访问相机</string>
<!-- 麦克风 -->
<key>NSMicrophoneUsageDescription</key>
<string>App需要您的同意,才能访问麦克风</string>
<!-- 位置 -->
<key>NSLocationUsageDescription</key>
<string>App需要您的同意,才能访问位置</string>
<!-- 在使用期间访问位置 -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>App需要您的同意,才能在使用期间访问位置</string>
<!-- 始终访问位置 -->
<key>NSLocationAlwaysUsageDescription</key>
<string>App需要您的同意,才能始终访问位置</string>
<!-- 日历 -->
<key>NSCalendarsUsageDescription</key>
<string>App需要您的同意,才能访问日历</string>
<!-- 提醒事项 -->
<key>NSRemindersUsageDescription</key>
<string>App需要您的同意,才能访问提醒事项</string>
<!-- 运动与健身 -->
<key>NSMotionUsageDescription</key> <string>App需要您的同意,才能访问运动与健身</string>
<!-- 健康更新 -->
<key>NSHealthUpdateUsageDescription</key>
<string>App需要您的同意,才能访问健康更新 </string>
<!-- 健康分享 -->
<key>NSHealthShareUsageDescription</key>
<string>App需要您的同意,才能访问健康分享</string>
<!-- 蓝牙 -->
<key>NSBluetoothPeripheralUsageDescription</key>
<string>App需要您的同意,才能访问蓝牙</string>
<!-- 媒体资料库 -->
<key>NSAppleMusicUsageDescription</key>
<string>App需要您的同意,才能访问媒体资料库</string>
<h1>1.照片的存储(这里会用两个方法实现,一种是与其他照片一样存在set里,另一种是新创建一个set存储)</h1>
- 点击图片
- 控制器传参
- 显示在ScrollView上, 并设置好图片的宽高
方法一
self.imageView.userInteractionEnabled = YES;
[self.imageView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(seeBig)]];
ZJSeeBigViewController *seeBig = [[ZJSeeBigViewController alloc] init];
seeBig.topic = self.topic;
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:seeBig animated:YES completion:nil];
// scrollView
UIScrollView *scrollView = [[UIScrollView alloc] init];
scrollView.delegate = self;
scrollView.frame = [UIScreen mainScreen].bounds;
[self.view insertSubview:scrollView atIndex:0];
// scrollView.backgroundColor = [UIColor redColor];
// scrollView.frame = self.view.bounds;
// scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
// imageView
UIImageView *imageView = [[UIImageView alloc] init];
[imageView sd_setImageWithURL:[NSURL URLWithString:self.topic.large_image] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (image == nil) return; // 图片下载失败
self.saveButton.enabled = YES;
}];
[scrollView addSubview:imageView];
imageView.xmg_width = scrollView.xmg_width;
imageView.xmg_height = self.topic.height * imageView.xmg_width / self.topic.width;
imageView.xmg_x = 0;
if (imageView.xmg_height >= scrollView.xmg_height) { // 图片高度超过整个屏幕
imageView.xmg_y = 0;
// 滚动范围
scrollView.contentSize = CGSizeMake(0, imageView.xmg_height);
} else { // 居中显示
imageView.xmg_centerY = scrollView.xmg_height * 0.5;
}
self.imageView = imageView;
// 缩放比例
CGFloat scale = self.topic.width / imageView.xmg_width;
if (scale > 1.0) {
scrollView.maximumZoomScale = scale;
}
- (IBAction)save {
UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if (error) {
[SVProgressHUD showErrorWithStatus:@"图片保存失败!"];
} else {
[SVProgressHUD showSuccessWithStatus:@"图片保存成功!"];
}
}
方法二(这里涉及到一个新的类库<Photos/Photos.h> 在保存照片的时候,我们需要先判断手机里是否有改软件已经存储的collectionSet 如果有直接往里存,没有要创建,保存之前会涉及到一个用户quan)
#import "XMGSeeBigViewController.h"
#import "XMGTopic.h"
#import <UIImageView+WebCache.h>
// #import <AssetsLibrary/AssetsLibrary.h> // iOS9开始废弃
#import <Photos/Photos.h> // iOS9开始推荐
#import <SVProgressHUD.h>
@interface XMGSeeBigViewController () <UIScrollViewDelegate>
/** 图片控件 */
@property (nonatomic, weak) UIImageView *imageView;
@property (weak, nonatomic) IBOutlet UIButton *saveButton;
@end
@implementation XMGSeeBigViewController
static NSString * XMGAssetCollectionTitle = @"5期-百思不得姐";
//点击保存按钮
- (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];
});
}
#pragma mark - <UIScrollViewDelegate>
/**
* 返回一个scrollView的子控件进行缩放
*/
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
<h1>2.利用UIImagePickerController取照片照片</h1>
iOS 获取图片有三种方法:
1. 直接调用摄像头拍照
2. 从相册中选择
3. 从图库中选择
UIImagePickerController 类来获取图片视频,大体分为以下几个步骤:
1. 初始化UIImagePickerController 类;
2. 设置UIImagePickerController 实例的数据来源类型(下面解释);
3. 设置设置代理;
4. 如果需要做图片修改的话设置allowsEditing =yes。
数据来源类型一共有三种:
enum {
UIImagePickerControllerSourceTypePhotoLibrary ,//来自图库
UIImagePickerControllerSourceTypeCamera ,//来自相机
UIImagePickerControllerSourceTypeSavedPhotosAlbum //来自相册
};
获取图片首先签订两个协议
@interface MainViewController ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate>
在点击方法内模态推出UIImagePickerController
从相册选取(需给用户选择哪种方式获取图片)
/**
* 利用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];
}
实现代理方法
//选择完图片后会回调 didFinishPickingMediaWithInfo 这个方法
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
NSLog(@"info = %@",info);
//隐藏控制器
[picker dismissViewControllerAnimated:YES completion:nil];
//给imageView 赋值图片
imageView.image = [info objectForKey:UIImagePickerControllerEditedImage];
}
//导航条上面的 Cancel 的点击方法
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
//隐藏控制器
[picker dismissViewControllerAnimated:YES completion:nil];
}