快速访问照片库

2024-02-17

我想在我的应用程序中访问用户照片库中的照片,并且我正在查看 UIImagePickerController 来执行此操作。但是,我想知道是否可以访问和查看照片库中的照片而不实际将这些照片存储在应用程序中?因此基本上该应用程序将存储对所选照片的​​引用,而不是存储照片本身。这是为了防止应用程序占用大量空间来存储每张照片。

Thanks!


这并不那么简单,但正如 Rob 提到的,您可以保存照片资源 url,然后使用照片框架获取它。您可以使用 PHImageManager 方法 requestImageData 获取它们。

import UIKit
import Photos
class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
    @IBOutlet weak var imageView: UIImageView!
    let galleryPicker = UIImagePickerController()
    // create a method to fetch your photo asset and return an UIImage on completion
    override func viewDidLoad() {
        super.viewDidLoad()
        // lets add a selector to when the user taps the image
        imageView.isUserInteractionEnabled = true
        imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(openPicker)))
        // request authorization
        switch PHPhotoLibrary.authorizationStatus() {
        case .authorized:
            print("The user has explicitly granted your app access to the photo library.")
            return
        case .denied:
            print("The user has explicitly denied your app access to the photo library.")
        case .notDetermined:
            PHPhotoLibrary.requestAuthorization { status in
                print("status", status)
            }
        case .restricted:
            print("Your app is not authorized to access the photo library, and the user cannot grant such permission.")
        default: break
        }
    }
    // opens the image picker for photo library
    @objc func openPicker(_ gesture: UITapGestureRecognizer) {
        galleryPicker.sourceType = .photoLibrary
        galleryPicker.delegate = self
        present(galleryPicker, animated: true)
    }
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.imageView.contentMode = .scaleAspectFit
        // check if there is an url saved in the user defaults
        // and fetch its first object (PHAsset)
        if let assetURL = UserDefaults.standard.url(forKey: "assetURL") {
            if let asset = PHAsset.fetchAssets(withALAssetURLs: [assetURL], options: nil).firstObject {
                asset.asyncImageData { data, _, _, _ in
                    print("fetched")
                    guard let data = data else { return }
                    self.imageView.image = UIImage(data: data)
                }
            } else {
                print("assetURL:", assetURL)
                self.imageView.image = UIImage(contentsOfFile: assetURL.path)
            }
        } else {
            print("no assetURL found")
        }

    }
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true)
        print("canceled")
    }
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {

        self.imageView.image = info[.originalImage] as? UIImage
        if let phAsset = info[.phAsset] as? PHAsset {
            phAsset.asyncURL { url in
                guard let url = url else { return }
                UserDefaults.standard.set(url, forKey: "assetURL")
                print("assetURL saved")
            }
        }
        dismiss(animated: true)
    }
}

extension PHAsset {
    func asyncURL(_ completion: @escaping ((URL?) -> Void)) {
        switch mediaType {
        case .image:
            let options: PHContentEditingInputRequestOptions = .init()
            options.canHandleAdjustmentData = { _ in true }
            requestContentEditingInput(with: options) { editingInput, _ in
                completion(editingInput?.fullSizeImageURL)
            }
        case .video:
            let options: PHVideoRequestOptions = .init()
            options.version = .original
            PHImageManager.default()
                .requestAVAsset(forVideo: self, options: options) { asset, _, _ in
                completion((asset as? AVURLAsset)?.url)
            }
        default:
            completion(nil)
        }
    }
    func asyncImageData(version: PHImageRequestOptionsVersion = .original, completion: @escaping  (Data?, String?, UIImage.Orientation, [AnyHashable : Any]?) -> ()) {
        let options = PHImageRequestOptions()
        options.version = version
        PHImageManager.default()
            .requestImageData(for: self, options: options, resultHandler: completion)
    }
}
extension URL {
    var phAsset: PHAsset? {
        PHAsset.fetchAssets(withALAssetURLs: [self], options: nil).firstObject
    }
}

注意:不要忘记编辑您的信息 plist 并添加“隐私 - 照片库使用说明”

Sample https://www.dropbox.com/s/9532ae6n0zs3slf/asset%20urls.zip?dl=1

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

快速访问照片库 的相关文章

随机推荐

  • 如何将注释与 faces-config.xml 混合

    使用 JBoss 6 0 0 Final Richfaces 3 3 3 Final MyFaces 2 0 6 facelets 1 1 15 B1 RF 3 的限制 我正在处理一个遗留项目 其中包含数百个定义的beanfaces con
  • 在控制台应用程序中获取屏幕分辨率

    如何在控制台应用程序中获取屏幕分辨率 如果可能 而在Forms我可以用 int height Screen PrimaryScreen Bounds Height int width Screen PrimaryScreen Bounds
  • Nuxt 与 LocomotiveScroll 和 Gsap

    我一直在努力实施机车卷轴 https github com locomotivemtl locomotive scroll and Gsap https greensock com gsap 进入 Nuxt 项目 我认为这与 DOM 和 S
  • Rails rake 任务是否提供对 ActiveRecord 模型的访问?

    我正在尝试创建自定义 rake 任务 但似乎我无权访问我的模型 我认为这是 Rails 任务中隐含的内容 我在 lib tasks test rake 中有以下代码 namespace test do task new task do pu
  • Heroku 应用程序(播放)在本地工作正常,然后不保存到服务器上的数据库

    在 Heroku 上使用 Play V2 在本地测试时一切正常 但当我部署到 Heroku 并尝试保存到 PostgreSQL 数据库时 出现以下错误 在我的 Procfile 中有这个 web target start Dhttp por
  • 在 Razor 中使用一个提交按钮提交两个 HTML 表单

    首先 我很抱歉我的英语不好 我是 ASP NET MVC 的新手 目前我正在用它做小型 租车 项目 我想制作一个表单 页面管理员可以在页面上添加汽车 其中包含详细信息 例如name year of production and pictur
  • Java 中的列表、队列和集合

    列表 队列和集合有什么区别 简单来说 A list是对象的有序列表 其中同一对象很可能出现多次 例如 1 7 1 3 1 1 1 5 谈论列表中的 第三个元素 是有意义的 您可以在列表中的任意位置添加元素 更改列表中的任意位置的元素或从列表
  • 在 MATLAB 中保存的 MPEG4 质量

    我需要从加载到 matlab 并编辑 逐帧 的原始 mpeg4 视频中获取 mpeg4 文件以在另一个应用程序中使用 为此 我尝试使用 VideoWriter 将质量设置为 100 newVid VideoWriter outputfile
  • 是什么原因导致 VoiceOver 宣布空组?

    我们有以下 简化的 HTML 真正的 HTML 有点复杂 但是listitem元素是exactly如下面的代码片段所示 div div Foo div div Bar div div Baz div div 当用户向下浏览列表时 Voice
  • 如何在 Swift 中的 UITableViewCell 上添加带有单击事件的按钮?

    在我的主页中 我为 UITableViewCell 创建了一个 xib 文件 我正在从该 xib 文件加载单元格 并且它工作正常 单元格内部有一些标签和按钮 我的目标是通过单击单元格上的按钮来更改标签 我的代码喜欢下面 import UIK
  • android studio 的最低硬件要求?

    我的系统配置 Intel Pentiunm 双核 1 3GHz 2GB RAM 我已经安装了 Android Studio 但它很慢 我是 Android 开发的新手 将 RAM 升级到 4GB 有帮助吗 我有一台具有以下配置的笔记本电脑
  • 是否存在逆向“成员”?红宝石中的方法?

    我经常发现自己在检查某个值是否属于某个集合 据我了解 人们通常使用Enumerable member 为了这 end index member word 1 3 2 然而 这感觉比 Ruby 中的大多数东西不太优雅 我宁愿把这段代码写成 e
  • 由于“CALayer 边界包含 NaN:[nan 0; nan 15.1]”而发生崩溃

    我遇到以下崩溃 CALayerInvalidGeometry CALayerInvalidGeometry CALayer bounds contains NaN nan 0 nan 15 1 这段代码的最后一行 CGRect bounds
  • 使用 numpy 进行元素“in”的 Pythonic 且有效的方法

    我正在寻找一种有效获取布尔数组的方法 其中给定两个大小相等的数组a and b 如果对应的元素为真 则每个元素为真a出现in的对应元素b 例如 以下程序 a numpy array 1 2 3 4 b numpy array 1 2 13
  • ESB MULE 将参数传递给 java 方法

    我使用MULE版本3 3 0 CE 我想从入站标头获取一些值 然后将其传递给java方法 在java方法中对传递的值进行一些更改 最后我再次将其从java方法传递到出站 而不是将 Java bean 绑定到 Mule API 使用Calla
  • 使用 HornetQ 强制消息顺序

    我已经设置了一个 jms 服务器 其中 HornetQ 作为 JMS 提供者 队列 我有一个应用程序充当生产者 另一个应用程序 不同的计算机 充当消费者 我知道 JMS 规范不保证传递的顺序 但我正在寻找一种方法来做到这一点 接收消息exa
  • 如何使用 Python 函数将多个值添加到键中

    class my dict dict init function def init self self dict Function to add key value def add self key value self key value
  • Java 的算术精度更高

    我正在用 Java 构建一个 Web 应用程序 它可以进行数学运算并向用户显示步骤 当使用小数进行基本算术时 我经常会得到准确输出的混乱结果 这是我的问题 double a 0 15 double b 0 01 System out pri
  • 了解 C++ 成员函数模板特化

    我有以下课程 pragma once include
  • 快速访问照片库

    我想在我的应用程序中访问用户照片库中的照片 并且我正在查看 UIImagePickerController 来执行此操作 但是 我想知道是否可以访问和查看照片库中的照片而不实际将这些照片存储在应用程序中 因此基本上该应用程序将存储对所选照片