我正在构建一个用于清理用户照片库的应用程序,但在访问视频时遇到了障碍。这是访问和编辑照片的代码:
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 导入。
我认为您的做法是正确的
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
或两者都使用,这些数字感觉适合我的照片库。