SwiftUI 2.0:使用.fileExporter修饰符导出图像 [英] SwiftUI 2.0: export images with .fileExporter modifier

查看:129
本文介绍了SwiftUI 2.0:使用.fileExporter修饰符导出图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目标:使用新的.fileExporter修饰符通过SwiftUI导出图像

Goal: export images with SwiftUI using the new .fileExporter modifier

问题:目标图像未传递到.fileExporter文档.

Problem: The target image is not passing to .fileExporter document.

问题:如何获取.fileExporter修饰符以导出图像?

Question: How can I get .fileExporter modifier to export images?

struct ContentView: View {
    
    @State private var openFile = false
    @State private var exportFile = false


    @State private var img1 = UIImage()
    @State private var img2 = UIImage()

    @State private var target: Binding<UIImage>?    // dynamic target for importer
    
    var body: some View {
        Form {
            //image 1
            Button(action: {
                    self.target = $img1
                self.openFile.toggle()
            }){
                
                Image(uiImage: self.img1)
                .renderingMode(.original)
                .resizable()
                .frame(width: 48, height: 48)
                .clipShape(Circle())
            }
            
            //image 2
            Button(action: {
                    self.target = $img2
                self.openFile.toggle()
            }){
                
                Image(uiImage: self.img2)
                .renderingMode(.original)
                .resizable()
                .frame(width: 48, height: 48)
                .clipShape(Circle())
            }
        }
        .navigationTitle("File Importer")


        //file exporter not working. not sure what I should input as "document"
        .fileExporter(isPresented: $exportFile, document: target, contentType: .image) { result in
            if case .success = result {
                // Handle success.
            } else {
                // Handle failure.
            }
        }

        //file importer
        .fileImporter(isPresented: $openFile, allowedContentTypes: [.image]) { (res) in
            do{
                let fileUrl = try res.get()
                print(fileUrl)
                
                guard fileUrl.startAccessingSecurityScopedResource() else { return }
                if let imageData = try? Data(contentsOf: fileUrl),
                let image = UIImage(data: imageData) {
                    self.target?.wrappedValue = image
                }
                fileUrl.stopAccessingSecurityScopedResource()
                
            } catch{
                
                print ("error reading")
                print (error.localizedDescription)
            }
        }
    }
}

推荐答案

我发现了两个代码问题和两个逻辑问题.这是我的编辑版本:

There were a couple of code problems and a couple of logic problems that I found. Here's my edited version:

struct ContentView: View {
    
    @State private var openFile = false
    @State private var exportFile = false


    @State private var img1 = UIImage(named: "0")!
    @State private var img2 = UIImage(named: "1")!

    @State private var target : UIImage?
    
    var body: some View {
        Form {
            //image 1
            Button(action: {
                self.target = img1
                self.exportFile.toggle()
                //self.openFile.toggle()
            }){
                
                Image(uiImage: self.img1)
                .renderingMode(.original)
                .resizable()
                .frame(width: 48, height: 48)
                .clipShape(Circle())
            }
            
            //image 2
            Button(action: {
                self.target = img2
                self.exportFile.toggle()
                //self.openFile.toggle()
            }){
                
                Image(uiImage: self.img2)
                .renderingMode(.original)
                .resizable()
                .frame(width: 48, height: 48)
                .clipShape(Circle())
            }
        }
        .navigationTitle("File Importer")

        .fileExporter(isPresented: $exportFile, document: ImageDocument(image: target), contentType: .png, onCompletion: { (result) in
            if case .success = result {
                print("Success")
            } else {
                print("Failure")
            }
        })


        //file importer
        .fileImporter(isPresented: $openFile, allowedContentTypes: [.image]) { (res) in
            do{
                let fileUrl = try res.get()
                print(fileUrl)
                
                guard fileUrl.startAccessingSecurityScopedResource() else { return }
                if let imageData = try? Data(contentsOf: fileUrl),
                let image = UIImage(data: imageData) {
                    self.target = image
                }
                fileUrl.stopAccessingSecurityScopedResource()
                
            } catch{
                
                print ("error reading")
                print (error.localizedDescription)
            }
        }
    }
}

struct ImageDocument: FileDocument {
    
    static var readableContentTypes: [UTType] { [.png] }

    var image: UIImage

    init(image: UIImage?) {
        self.image = image ?? UIImage()
    }

    init(configuration: ReadConfiguration) throws {
        guard let data = configuration.file.regularFileContents,
              let image = UIImage(data: data)
        else {
            throw CocoaError(.fileReadCorruptFile)
        }
        self.image = image
    }

    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        return FileWrapper(regularFileWithContents: image.pngData()!)
    }
    
}

要看的东西:

  1. 逻辑错误:您有一个 exportFile 状态变量,但从未修改过它.这意味着 fileExporter 将永远不会出现.
  2. 您正在将 Binding< UIImage> 传递给需要 FileDocument 的函数.我为图像编写了一个简单的 FileDocument 实现.
  3. 因为我将您的 openFile 开关切换为 exportFile ,所以您现在没有任何 openFile 访问权限.这是您决定何时/如何触发这些的逻辑决定.
  4. 我也没有对图像进行任何错误处理,因此决定将所有内容都视为PNG.您可能需要做出不同的选择.
  1. Logic error: you had an exportFile state variable, but you never modified it. That would mean fileExporter would never present.
  2. You were passing a Binding<UIImage> to a function that wants a FileDocument. I wrote a simple FileDocument implementation for images.
  3. Because I switched out your openFile toggles for exportFile, you now don't have any openFile access. That's a logic decision for you to figure out when/how to trigger those.
  4. I also didn't do any error handling for the images and made a decision to treat everything as a PNG. You may want to make different choices.

请注意,我还使用了名为"0"的图像,和"1"表示-这些是我的示例项目所特有的.更改这些内容以适合您的项目.

Note that I also used images named "0" and "1" -- those were specific to my sample project. Change those to fit what works for your project.

如果您需要其他类型的解决方案,也可以使用 \.exportFiles 操作:

If you want a different type of solution to this, you can also look at using the \.exportFiles action: https://www.hackingwithswift.com/quick-start/swiftui/how-to-export-files-using-exportfilesaction

这篇关于SwiftUI 2.0:使用.fileExporter修饰符导出图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆