如何解决错误:从PHCachingImageManager调用requestImage时,IOSurfaceCreate'RGBA'失败
我正在使用PHCachingImageManager来获取iOS照片库中所有图像的缩略图,然后使用SwiftUI列表进行渲染。它似乎只适用于少量图像(例如,模拟器加载的六个图像),但是考虑到1000幅图像,我会多次出现此错误。
IIO_CreateIOSurfaceWithFormatandBuffer:594: *** ERROR: IOSurfaceCreate 'RGBA' Failed - clientAddress: 0x14d6a0000 allocSize: 0x00072000 size: 256 x 456 rb: 1024 [0x00000400] bpp: 4
这是什么意思,根本原因是什么?是否需要限制对PHCachingImageManager的访问?
下面是类似于我的应用程序中的一类,可在我的iPhone SE2上重现该问题。
import Foundation
import SwiftUI
import UIKit
import Photos
let thumbnailSize = CGSize(width: 90,height: 90)
struct PhotoSelectView: View {
class ImageRowManager {
let thumbnailImageRequestOptions: PHImageRequestOptions
let cachingImageManager = PHCachingImageManager()
var rows: [SelectableImageRow] = []
init() {
let options = PHImageRequestOptions()
options.isSynchronous = true
options.resizeMode = .fast
options.deliveryMode = .highQualityFormat
options.isNetworkAccessAllowed = false
self.thumbnailImageRequestOptions = options
}
func add(row: SelectableImageRow) {
self.rows.append(row)
}
}
struct SelectableImageRow: Hashable {
var rowIndex: Int
var images: [SelectableImage]
func hash(into hasher: inout Hasher) {
hasher.combine(self.rowIndex)
}
}
class SelectableImage: Hashable,ObservableObject {
@Published var image: UIImage? = nil
let id: String
private let asset: PHAsset
private let imageRowManager: ImageRowManager
init(asset: PHAsset,imageRowManager: ImageRowManager) {
self.id = asset.localIdentifier
self.asset = asset
self.imageRowManager = imageRowManager
self.loadImage()
}
func loadImage() {
dispatchQueue.global(qos: .background).async {
self.imageRowManager.cachingImageManager.requestimage(for: self.asset,targetSize: CGSize(width: 150,height: 150),contentMode: .aspectFill,options: self.imageRowManager.thumbnailImageRequestOptions) { (image,_) in
RunLoop.main.perform {
self.image = image
}
}
}
}
func hash(into hasher: inout Hasher) {
hasher.combine(self.id)
}
static func ==(lhs: SelectableImage,rhs: SelectableImage) -> Bool {
return lhs.id == rhs.id
}
}
let imageRowManager = ImageRowManager()
@State var selected = Set<SelectableImage>()
@State var grid: [SelectableImageRow] = []
var body: some View {
vstack {
vstack {
if !self.grid.isEmpty {
HStack {
Text("Pick images")
Spacer()
}
.padding(.leading)
.padding(.top)
ImagesScrollView(grid: self.$grid,selected: self.$selected)
Button(action: {
self.handleSelectButton()
}) {
Text("Select")
.foregroundColor(Color.black.opacity((self.selected.count != 0) ? 1 : 0.5))
.padding(.vertical,10)
.frame(width: UIScreen.main.bounds.width / 2)
.overlay(
Capsule(style: .continuous)
.stroke(Color.black.opacity((self.selected.count != 0) ? 1 : 0.5),style: strokeStyle(linewidth: 5))
)
}
.background(Color.white)
.padding(.bottom)
.disabled((self.selected.count != 0) ? false : true)
}
}
.frame(width: UIScreen.main.bounds.width - CGFloat(horizontalPadding),height: UIScreen.main.bounds.height / 1.5)
.background(Color.white)
.cornerRadius(12)
}
.background(Color.black.opacity(0.1)).edgesIgnoringSafeArea(.all)
.onAppear {
PHPhotoLibrary.requestAuthorization { status in
if status == .authorized {
self.getAllImages()
} else {
print("Cannot access photo library")
}
}
}
}
private func handleSelectButton() {
print("selected images",self.selected)
}
private func getAllImages() {
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate",ascending: false)]
let req = PHAsset.fetchAssets(with: .image,options: fetchOptions)
var rowIndex = 0
for i in stride(from: 0,to: req.count,by: gridItemWidth) {
var iteration : [SelectableImage] = []
for j in i..<i+gridItemWidth {
if j < req.count{
iteration.append(SelectableImage(asset: req[j],imageRowManager: self.imageRowManager))
}
}
let row = SelectableImageRow(rowIndex: rowIndex,images: iteration)
imageRowManager.add(row: row)
rowIndex += 1
}
self.grid = imageRowManager.rows
}
// Subviews
struct ImagesScrollView: View {
@Binding var grid: [SelectableImageRow]
@Binding var selected: Set<SelectableImage>
var body: some View {
List(self.grid,id: \.self) { row in
SelectableImageRowView(row: row,selected: self.$selected)
}
}
}
struct SelectableImageRowView: View {
var row: SelectableImageRow
@Binding var selected: Set<SelectableImage>
var body: some View {
HStack(spacing: 2) {
ForEach(row.images,id: \.self) { img in
SelectableImageCard(data: img,selected: self.$selected)
}
}
}
}
struct SelectableImageCard: View {
@Observedobject var data: SelectableImage
@Binding var selected: Set<SelectableImage>
var body: some View {
ZStack {
Image(uiImage: self.image()).resizable()
if self.selected.contains(self.data) {
Image(systemName: "checkmark")
.resizable()
.padding(7)
.foregroundColor(.white)
.background(Color.blue)
.clipShape(Circle())
.overlay(Circle().stroke(Color.white,linewidth: 1))
.frame(width: 30,height: 30,alignment: .topTrailing)
.offset(x: 30,y: -28)
}
}
.frame(width: thumbnailSize.width,height: thumbnailSize.height)
.onTapGesture {
if !self.selected.contains(self.data) {
self.selected.insert(self.data)
} else{
self.selected.remove(self.data)
}
}
}
private func image() -> some UIImage {
if let image = self.data.image {
return image
} else {
return UIImage(systemName: "heart.fill")!
}
}
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。