微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

错误:从PHCachingImageManager调用requestImage时,IOSurfaceCreate'RGBA'失败

如何解决错误:从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 举报,一经查实,本站将立刻删除。