SwiftUI:使用 .fileImporter 加载图像
Posted
技术标签:
【中文标题】SwiftUI:使用 .fileImporter 加载图像【英文标题】:SwiftUI: loading images with .fileImporter 【发布时间】:2020-11-23 19:06:30 【问题描述】:目标是使用新的 .fileImporter 修饰符加载 2 个不同的图像(图像 1 和 2)。
问题是我将相同的图像加载到两个缩略图(图像 1 和 2)。
有没有人设法用 .fileImporter 修饰符做到这一点?
import SwiftUI
struct ContentView: View
@State var openFile = false
@State var img1 = UIImage()
@State var img2 = UIImage()
@State var fileName = ""
var body: some View
Form
//image 1
Button(action:
self.openFile.toggle()
)
Image(uiImage: self.img1)
.renderingMode(.original)
.resizable()
.frame(width: 48, height: 48)
.clipShape(Circle())
//image 2
Button(action:
self.openFile.toggle()
)
Image(uiImage: self.img2)
.renderingMode(.original)
.resizable()
.frame(width: 48, height: 48)
.clipShape(Circle())
.navigationTitle("File Importer")
//file importer
.fileImporter(isPresented: $openFile, allowedContentTypes: [.image]) (res) in
do
let fileUrl = try res.get()
print(fileUrl)
self.fileName = fileUrl.lastPathComponent
fileUrl.startAccessingSecurityScopedResource()
if let imageData = try? Data(contentsOf: fileUrl),
let image = UIImage(data: imageData)
self.img1 = image
self.img2 = image
fileUrl.stopAccessingSecurityScopedResource()
catch
print ("error reading")
print (error.localizedDescription)
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【问题讨论】:
但是你是故意在self.img1 = image; self.img2 = image
这样做的……所以呢?
对不起,Asperi... 这样做的想法是:如果让 imageData = 试试?数据(contentsOf:fileUrl),让图像= UIImage(数据:imageData)self.img1=image1让图像=UIImage(数据:imageData)self.img2=image2
这可能不正确....如果您能提供一些帮助,我们将不胜感激! :)
【参考方案1】:
嗯...我会将文件导入器移动到单独的视图中以使用绑定,具体取决于点击的按钮。
更新:Form
的工作变体。使用 Xcode 12.1 / iOS 14.1 测试
struct ContentView: View
@State private var openFile = 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 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)
这是可能的解决方案(以防万一),但不适用于Form
:
struct ImportContentView: View
@State var openFile = false
@State var img1 = UIImage()
@State var img2 = UIImage()
var body: some View
//Form // << does not work for Form !!
VStack
//image 1
Button(action:
self.openFile.toggle()
)
Image(uiImage: self.img1)
.renderingMode(.original)
.resizable()
.frame(width: 48, height: 48)
.clipShape(Circle())
.background(LoaderView(isActive: $openFile, image: $img1))
//image 2
Button(action:
self.openFile.toggle()
)
Image(uiImage: self.img2)
.renderingMode(.original)
.resizable()
.frame(width: 48, height: 48)
.clipShape(Circle())
.background(LoaderView(isActive: $openFile, image: $img2))
.navigationTitle("File Importer")
struct LoaderView: View
@Binding var isActive: Bool
@Binding var image: UIImage
var body: some View
Color.clear
.fileImporter(isPresented: $isActive, 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.image = image
fileUrl.stopAccessingSecurityScopedResource()
catch
print ("error reading")
print (error.localizedDescription)
【讨论】:
感谢@Asperi!这似乎更合乎逻辑!但文件选择器未在此代码上打开...它对您有用吗? 你是对的 - 从头部发布。该变体在Form
中不起作用(原因不明)。立即查看更新和测试。【参考方案2】:
此解决方案适用于 Form。
struct FileImporterView: View
@State var openFile = false
@State var images = [UIImage(), UIImage()]
@State var index = 0
var body: some View
Form
ForEach(Array(0..<images.count), id: \.self) id in
Button(action:)
ImageRow(isPresenting: $openFile, img: $images[id], index: $index, id: id)
.navigationTitle("File Importer")
.fileImporter(isPresented: $openFile, allowedContentTypes: [.image], onCompletion: importImage)
func importImage(_ res: Result<URL, Error>)
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.images[index] = image
fileUrl.stopAccessingSecurityScopedResource()
catch
print ("error reading")
print (error.localizedDescription)
struct ImageRow: View
@Binding var isPresenting: Bool
@Binding var img: UIImage
@Binding var index: Int
var id: Int
init(isPresenting: Binding<Bool>, img: Binding<UIImage>, index: Binding<Int>, id: Int)
self._isPresenting = isPresenting
self._img = img
self._index = index
self.id = id
var body: some View
HStack
Image(uiImage: img)
.renderingMode(.original)
.resizable()
.frame(width: 48, height: 48)
.clipShape(Circle())
Spacer()
.contentShape(Rectangle())
.onTapGesture
self.index = id
self.isPresenting = true
【讨论】:
以上是关于SwiftUI:使用 .fileImporter 加载图像的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SwiftUI 中使用 .fileimporter 保存音频文件并检索文件并在 SwiftUI 列表中显示它们的文件名?