1.info中写上

<key>NSCameraUsageDescription</key>
<string>需要您的同意才能读取媒体资料库</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>需要您的同意才能读取媒体资料库</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>需要您的同意才能读取媒体资料库</string>
<key>Privacy - Photo Library Usage Description</key>
<string>需要您的同意才能读取媒体资料库</string>

2.保存

import Photos

//操作结果枚举
enum PhotoAlbumUtilResult {
case success, error, denied
} //相册操作工具类
class PhotoAlbumUtil: NSObject { public typealias completion = ((_ result: PhotoAlbumUtilResult) -> ())
//判断是否授权
class func isAuthorized() -> Bool {
return PHPhotoLibrary.authorizationStatus() == .authorized ||
PHPhotoLibrary.authorizationStatus() == .notDetermined } //保存图片到相册
class func saveImageInAlbum(image: UIImage, albumName: String,
completion: completion?) {
//权限验证
if !isAuthorized() {
completion?(.denied)
return
}
var assetAlbum: PHAssetCollection? //如果指定的相册名称为空,则保存到相机胶卷。(否则保存到指定相册)
if albumName.isEmpty {
let list = PHAssetCollection
.fetchAssetCollections(with: .smartAlbum, subtype: .smartAlbumUserLibrary,
options: nil)
assetAlbum = list[0]
} else {
//看保存的指定相册是否存在
let list = PHAssetCollection
.fetchAssetCollections(with: .album, subtype: .any, options: nil)
list.enumerateObjects({ (album, index, stop) in
let assetCollection = album
if albumName == assetCollection.localizedTitle {
assetAlbum = assetCollection
stop.initialize(to: true)
}
})
//不存在的话则创建该相册
if assetAlbum == nil {
PHPhotoLibrary.shared().performChanges({
PHAssetCollectionChangeRequest
.creationRequestForAssetCollection(withTitle: albumName)
}, completionHandler: { (isSuccess, error) in
self.saveImageInAlbum(image: image, albumName: albumName,
completion: completion)
})
return
}
} //保存图片
PHPhotoLibrary.shared().performChanges({
//添加的相机胶卷
let result = PHAssetChangeRequest.creationRequestForAsset(from: image)
//是否要添加到相簿
if !albumName.isEmpty {
let assetPlaceholder = result.placeholderForCreatedAsset
let albumChangeRequset = PHAssetCollectionChangeRequest(for:
assetAlbum!)
albumChangeRequset!.addAssets([assetPlaceholder!] as NSArray)
}
}) { (isSuccess: Bool, error: Error?) in
if isSuccess {
completion?(.success)
} else{
print(error!.localizedDescription)
completion?(.error)
}
}
}
}

3.使用

PhotoAlbumUtil.saveImageInAlbum(image: image, albumName: "APP") { (result) in
DispatchQueue.main.async {
switch result{
case .success:
//"保存成功"
break
case .denied:
//没有权限,去设置里打开权限
let a = MyAlertController()
a.addOKView("去设置"){ (a) in
let url = URL(string: UIApplicationOpenSettingsURLString)
if let url = url, UIApplication.shared.canOpenURL(url) {
if #available(iOS 10, *) {
UIApplication.shared.open(url, options: [:],
completionHandler: {
(success) in
})
} else {
UIApplication.shared.openURL(url)
}
}
}
a.addCancelView()
a.show(self,title: "没有相册权限",message: "请您到 \"设置\" -> \"APP\" 开启相册权限", style: .alert )
break
case .error:
//"保存失败"
}
}
}

swift3.0 保存图片到本地,申请权限的更多相关文章

  1. Android6.0动态申请权限

    先直接看代码: public void onClick(View v){ onCallPermission(); } public void onCallPermission(){ if (Build ...

  2. 说说Android6.0动态申请权限的那些坑

    白天在做SDK23版本的适配,遇到了不少坑,现在抽空记下来,以此为戒. 首先要知道哪些坑,就得先了解一些定义和基本使用方式. 那么先介绍一下动态申请的权限分组情况. 下面的权限组是由谷歌官方定义的,目 ...

  3. Android6.0动态申请权限那些坑--以及避免用户选择不再提示后无法获取权限的问题

    Android 6.0 为了保护用户隐私,将一些权限的申请放在了应用运行的时候去申请, 比如以往的开发中,开发人员只需要将需要的权限在清单文件中配置即可,安装后用户可以在设置中的应用信息中看到:XX应 ...

  4. swift3.0 CoreGraphics绘图-实现画板

    swift3.0对绘图的API进行了优化,看起来更swift了. 看下UI的构造.设置画笔粗细.清空面板和保存到本地 下面直接看画板文件 这里我做的比较复杂,记录触摸到的每个点,再连成路径,其实直接用 ...

  5. Android笔记之使用ImageView加载网络图片以及保存图片到本地并更新图库

    ImageView显示网络图片 findViewById(R.id.btnLoad).setOnClickListener(new View.OnClickListener() { @Override ...

  6. 使用 swift3.0高仿新浪微博

    项目地址:https://github.com/SummerHH/swift3.0WeBo 使用 swift3.0 高仿微博,目前以实现的功能有,添加访客视图,用户信息授权,首页数据展示(支持正文中连 ...

  7. Android开发在Activity外申请权限调用相机打开相册

    问题描述: 最近在项目中遇到一个需要调用相册和打开相机的需求,但是,在Android 6.0以后,调用相册属于危险权限,需要开发者动态获取,这就意味着我们申请权限是与Activity绑定的,但如果一个 ...

  8. Android无需申请权限拨打电话

    Android打电话有两种实现方法: 第一种方法,拨打电话跳转到拨号界面.源代码如下: Intent intent = new Intent(Intent.ACTION_DIAL); Uri data ...

  9. Swift3.0变化分享

    Swift 3.0 做出的改变很大,在这篇文章中,我将尽我所能,利用代码样例给大家解释Swift 3.0最重要(要命)的改变,希望大家能够做好升级Swift 3.0 的准备.Swift 3.0的改变不 ...

随机推荐

  1. C/C++读写excel文件 的几种方式

    因为有些朋友问代码的问题,将OLE读写的代码分享在这个地方,大家请自己看. http://blog.csdn.net/fullsail/article/details/8449448 C++读取Exc ...

  2. 微软发布Azure Stack第一个技术预览版

    为了提升商业灵敏度和加快创新步伐,各个企业都在迅速地转向云服务.在微软,我们已经见到微软智能云Azure的飞速发展和使用,每月我们都有近十万的新增订阅量.然而,我们也了解到还有很多企业在完全移到公有云 ...

  3. STL算法分类记忆

    STL算法主要是我们强大的标准库中以迭代器或数值或函数对象为参数预先定义好的一系列算法操作. 在STL算法分类中首先要提的就是两个普遍存在的后缀: _if _copy 其中这两个后缀的作用分别是:一. ...

  4. 就linux三剑客简单归纳

    就linux三剑客简单归纳: :awk 习题1:用 awk 中查看服务器连接状态并汇总 netstat -an|awk '/^tcp/{++s[$NF]}END{for(a in s)print a, ...

  5. DedeCms织梦后台管理员密码修改和忘记重置方法

    方法/步骤 打开dede_admin数据表: 进入你的MYSQL后台,然后在你的数据库名中,找到dede_admin这项如图,pwd下的值就是你的密码,织梦密码采取的是MD5加密,破解麻烦而且没有必要 ...

  6. Java 基本IO操作

    1.基本IO操作     有时候我们编写的程序除了自身会定义一些数据信息外,还需要引用外界的数据,或是将自身的数据发送到外界,这时我们需要使用输入与输出. 1)输入与输出       输入:是一个从外 ...

  7. Doing Research Needs Efforts

    What is research?   From YouTube Video or baiduyun Links What does not? spend many hours before you ...

  8. spring的声明式事务,及redis事务。

    Redis的事务功能详解 http://ghoulich.xninja.org/2016/10/12/how-to-use-transaction-in-redis/ MULTI.EXEC.DISCA ...

  9. angular中ngOnChanges与组件变化检测的关系

    1.ngOnChanges只有在输入值改变的时候才会触发,如果输入值(@Input)是一个对象,改变对象内的属性的话是不会触发ngOnChanges的. 2.组件的变化检测: 2a.changeDet ...

  10. WSGI、flup、fastcgi、web.py、uwsgi

    ==================        网上别人的理解 =================== http://www.douban.com/note/13508388/ 1.Apache/ ...