SwiftUI 2.0:使用 .fileExporter 修饰符导出图像
SwiftUI 2.0: export images with .fileExporter modifier
目标:使用新的 .fileExporter 修饰符通过 SwiftUI 导出图像
问题:目标图像未传递到 .fileExporter 文档。
问:如何获取导出图片的.fileExporter修改器?
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)
}
}
}
}
我发现了一些代码问题和一些逻辑问题。这是我编辑的版本:
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()!)
}
}
要看的东西:
- 逻辑错误:您有一个
exportFile
状态变量,但您从未修改过它。这意味着 fileExporter
永远不会出现。
- 您将
Binding<UIImage>
传递给需要 FileDocument
的函数。我为图像编写了一个简单的 FileDocument
实现。
- 因为我关闭了
openFile
的 exportFile
开关,您现在没有任何 openFile
访问权限。这是一个合乎逻辑的决定,你需要找出 when/how 来触发这些。
- 我也没有对图像进行任何错误处理,并决定将所有内容都视为 PNG。您可能想要做出不同的选择。
请注意,我还使用了名为“0”和“1”的图像——它们是我的示例项目特有的。更改这些以适合您的项目。
如果您想要不同类型的解决方案,您还可以查看使用 \.exportFiles
操作:https://www.hackingwithswift.com/quick-start/swiftui/how-to-export-files-using-exportfilesaction
目标:使用新的 .fileExporter 修饰符通过 SwiftUI 导出图像
问题:目标图像未传递到 .fileExporter 文档。
问:如何获取导出图片的.fileExporter修改器?
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)
}
}
}
}
我发现了一些代码问题和一些逻辑问题。这是我编辑的版本:
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()!)
}
}
要看的东西:
- 逻辑错误:您有一个
exportFile
状态变量,但您从未修改过它。这意味着fileExporter
永远不会出现。 - 您将
Binding<UIImage>
传递给需要FileDocument
的函数。我为图像编写了一个简单的FileDocument
实现。 - 因为我关闭了
openFile
的exportFile
开关,您现在没有任何openFile
访问权限。这是一个合乎逻辑的决定,你需要找出 when/how 来触发这些。 - 我也没有对图像进行任何错误处理,并决定将所有内容都视为 PNG。您可能想要做出不同的选择。
请注意,我还使用了名为“0”和“1”的图像——它们是我的示例项目特有的。更改这些以适合您的项目。
如果您想要不同类型的解决方案,您还可以查看使用 \.exportFiles
操作:https://www.hackingwithswift.com/quick-start/swiftui/how-to-export-files-using-exportfilesaction