在 SwiftUI 中访问设备照片库中的视频

问题描述 投票:0回答:1

我正在构建一个用于清理用户照片库的应用程序,但在访问视频时遇到了障碍。这是访问和编辑照片的代码:

import Foundation
import Photos

class PhotosModel: ObservableObject {
    @Published var errorString : String = ""
    @Published var photoArray: [BetterUIImage] = []
    
    private var currentIndex = 0
    private var totalInitialPhotos = 0
    
    private var photosToDelete = [PHAsset]()
    
    init() {
        PHPhotoLibrary.requestAuthorization { (status) in
            DispatchQueue.main.async {
                switch status {
                case .authorized, .limited:
                    self.errorString = ""
                    self.getInitialPhotos()
                case .denied, .restricted:
                    self.errorString = "Photo access permission denied"
                case .notDetermined:
                    self.errorString = "Photo access permission not determined"
                @unknown default:
                    fatalError()
                }
            }
        }
    }
    
    fileprivate func getInitialPhotos() {
        let manager = PHImageManager.default()
        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = false
        requestOptions.deliveryMode = .highQualityFormat
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        
        let results: PHFetchResult = PHAsset.fetchAssets(with: fetchOptions)
        totalInitialPhotos = results.count
        
        if results.count > 2 {
            for i in 0..<3 {
                let asset = results.object(at: i)
                let size = CGSize(width: 700, height: 700) //You can change size here
                manager.requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: requestOptions) { (image, _) in
                    DispatchQueue.main.async {
                        if let image = image {
                            let betterImage = BetterUIImage(image: image, asset: asset)
                            self.photoArray.append(betterImage)
                        } else {
                            print("error asset to image")
                        }
                    }
                }
            }
            currentIndex = 3
        } else if results.count > 0 {
            for i in 0..<results.count {
                let asset = results.object(at: i)
                let size = CGSize(width: 700, height: 700) //You can change size here
                manager.requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: requestOptions) { (image, _) in
                    DispatchQueue.main.async {
                        if let image = image {
                            let betterImage = BetterUIImage(image: image, asset: asset)
                            self.photoArray.append(betterImage)
                        } else {
                            print("error asset to image")
                        }
                    }
                }
            }
        } else {
            DispatchQueue.main.async {
                self.errorString = "No photos to display"
            }
        }
        self.photoArray = self.photoArray.reversed()
        print("getAllPhotos() completed")
    }
    
    func appendToPhotosToDelete(_ asset: PHAsset) {
        photosToDelete.append(asset)
        print("appendToPhotosToDelete() completed")
    }
    
    fileprivate func getNextPhoto() {
        let manager = PHImageManager.default()
        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = false
        requestOptions.deliveryMode = .highQualityFormat
        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
        
        // TODO: Set change with .image to with fetchOptions: Gets all types
        let results: PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
        
        // TODO: Change photoArray so that it imcludes all three types
        self.photoArray = photoArray.shiftRight()
        
        let asset = results.object(at: currentIndex)
        let size = CGSize(width: 700, height: 700) //You can change size here
        
        // TODO: Make this so that it applies to Images, Lives, and Videos
        manager.requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: requestOptions) { (image, _) in
            DispatchQueue.main.async {
                if let image = image {
                    self.photoArray.removeLast()
                    self.photoArray.append(BetterUIImage(image: image, asset: asset))
                } else {
                    print("error asset to image")
                }
            }
        }
    }
    
    func next() {
        if currentIndex == totalInitialPhotos {
            self.photoArray = []
            return
        } else if currentIndex == totalInitialPhotos - 1 {
            self.photoArray.removeLast()
        } else if currentIndex == totalInitialPhotos - 2 {
            self.photoArray.removeLast()
        }
        
        getNextPhoto()
        
        currentIndex += 1
        print(currentIndex)
    }
    
    func deletePhoto() {
        PHPhotoLibrary.shared().performChanges({
            PHAssetChangeRequest.deleteAssets(NSArray(array: self.photosToDelete))
        })
    }
}

有没有办法编辑这个系统以返回图像和视频?我尝试将 PHAsset.fetchAssets(with: .image, options: fetchOptions) 调用更改为 HAsset.fetchAssets(with: fetchOptions)。这似乎不起作用,但也没有破坏任何东西。

还有其他方法可以做到这一点吗?我见过其他应用程序做了类似的事情,但我可以在网上找到的所有信息都涉及 PhotosPicker,这几乎违背了我的应用程序的目的。

编辑:删除不必要的 UIKit 导入。

ios swift swiftui gallery
1个回答
0
投票

我认为您的做法是正确的

PHAsset.fetchAssets(with: fetchOptions)
,因为这将允许返回多种媒体类型。您甚至可以在没有任何谓词的情况下使用它,但如果您想专门返回视频和图像,这适用于我的快速测试:

import Photos

let format = "(mediaType = %d)  || (mediaType = %d)"
let fetchOptions = PHFetchOptions()
fetchOptions.predicate = NSPredicate(format: format,
                                     argumentArray: [PHAssetMediaType.image.rawValue, PHAssetMediaType.video.rawValue])

let fetchResult = PHAsset.fetchAssets(with: fetchOptions)

fetchResult.count
会有所不同,具体取决于我是否在查询中仅使用
.video
.image
或两者都使用,这些数字感觉适合我的照片库。

© www.soinside.com 2019 - 2024. All rights reserved.