xcode SwiftUI:.fileExporter仅导出1个文档

cyej8jka  于 2023-02-09  发布在  Swift
关注(0)|答案(1)|浏览(141)

平台和版本iOS Xcode版本12.4(12D4e)
目标:使用SwiftUI. fileExporter修改器导出多个图像。
问题:在MacOS上使用NS Image时,导出所有图像。在iOS(iPad、Catalyst和iPhone)上使用UIImage时,仅导出1个图像
重现步骤

    • iOS代码:**
class AppContext: ObservableObject {
    @Published var fileSaveDialogShown = false
}

@main
struct ExportApp: App {
    @StateObject var appContext = AppContext()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(self.appContext)
                .fileExporter(
                    isPresented: $appContext.fileSaveDialogShown,
                    documents: [
                        ImageDocument(image: UIImage(named: "1")),
                        ImageDocument(image: UIImage(named: "2"))
                    ],
                    contentType: .png // Match this to your representation in ImageDocument
                ) { url in
                    print("Saved to", url) // [URL]
                }
        }
    }
}

import SwiftUI
import UniformTypeIdentifiers

struct ImageDocument: FileDocument {
    static var readableContentTypes: [UTType] { [.jpeg, .png, .tiff] }
    
    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 {
        // You can replace tiff representation with what you want to export
        return FileWrapper(regularFileWithContents: image.pngData()!)
    }
}

struct ContentView: View {
    
    @EnvironmentObject var appContext: AppContext
    
    var body: some View {
        VStack {
            Button(action: {
                appContext.fileSaveDialogShown.toggle()
            }, label: {
                Text("Button")
            })
        }
        .frame(width: 200, height: 200)
    }
}
    • MacOS代码:**
import SwiftUI

class AppContext: ObservableObject {
    @Published var fileSaveDialogShown = false
}

@main
struct FocalApp: App {
    @StateObject var appContext = AppContext()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(self.appContext)
                .fileExporter(
                    isPresented: $appContext.fileSaveDialogShown,
                    documents: [
                        ImageDocument(image: NSImage(named: "1")),
                        ImageDocument(image: NSImage(named: "2"))
                    ],
                    contentType: .jpeg // Match this to your representation in ImageDocument
                ) { url in
                    print("Saved to", url) // [URL]
                }
        }
    }
}


import SwiftUI
import UniformTypeIdentifiers

struct ImageDocument: FileDocument {
    static var readableContentTypes: [UTType] { [.jpeg, .png, .tiff] }
    
    var image: NSImage
    
    init(image: NSImage?) {
        self.image = image ?? NSImage()
    }
    
    init(configuration: ReadConfiguration) throws {
        guard let data = configuration.file.regularFileContents,
              let image = NSImage(data: data)
        else {
            throw CocoaError(.fileReadCorruptFile)
        }
        self.image = image
    }
    
    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        // You can replace tiff representation with what you want to export
        return FileWrapper(regularFileWithContents: image.tiffRepresentation!)
    }
}

struct ContentView: View {
    
    @EnvironmentObject var appContext: AppContext
    
    var body: some View {
        VStack {
            Button(action: {
                appContext.fileSaveDialogShown.toggle()
            }, label: {
                Text("Button")
            })
        }
        .frame(width: 200, height: 200)
    }
}
to94eoyn

to94eoyn1#

看起来你需要为每个导出的文件指定唯一的名称。如果没有明确的定义名称,两个图像都将被命名为"导出的PNG图像",所以第一个将被覆盖。
这对我很有效:

import SwiftUI

class AppContext: ObservableObject {
    @Published var fileSaveDialogShown = false
}

@main
struct ExportApp: App {
    @StateObject var appContext = AppContext()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(self.appContext)
                .fileExporter(
                    isPresented: $appContext.fileSaveDialogShown,
                    documents: [
                        ImageDocument(image: UIImage(named: "1"), name: "1"),
                        ImageDocument(image: UIImage(named: "2"), name: "2")
                    ],
                    contentType: .png // Match this to your representation in ImageDocument
                ) { url in
                    print("Saved to", url) // [URL]
                }
        }
    }
}

import SwiftUI
import UniformTypeIdentifiers

struct ImageDocument: FileDocument {
    static var readableContentTypes: [UTType] { [.jpeg, .png, .tiff] }
    
    var image: UIImage
    var name: String
    
    init(image: UIImage?, name: String) {
        self.image = image ?? UIImage()
        self.name = name
    }
    
    init(configuration: ReadConfiguration) throws {
        guard let data = configuration.file.regularFileContents,
              let image = UIImage(data: data)
        else {
            throw CocoaError(.fileReadCorruptFile)
        }
        self.image = image
        self.name = configuration.file.filename ?? "image"
    }
    
    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        // You can replace tiff representation with what you want to export
        let fileWrapper = FileWrapper(regularFileWithContents: image.pngData()!)
        fileWrapper.filename = self.name
        return fileWrapper
    }
}

struct ContentView: View {
    
    @EnvironmentObject var appContext: AppContext
    
    var body: some View {
        VStack {
            Button(action: {
                appContext.fileSaveDialogShown.toggle()
            }, label: {
                Text("Button")
            })
        }
        .frame(width: 200, height: 200)
    }
}

相关问题