如何从图像选择器中获取图像并显示到添加表单中?

How to get the image from image picker and display into a add form?

我有下面的结构来处理图像选择器,但我无法将选择的图像传递给要显示的视图。下面选定的路径正确地打印了文件的位置,但是如何将这个选定的文件分配给视图中的图片?

    struct FileView: View {
    var body: some View {
        Button("Select File") {
            let openPanel = NSOpenPanel()
            openPanel.prompt = "Select File"
            openPanel.allowsMultipleSelection = false
            openPanel.canChooseDirectories = false
            openPanel.canCreateDirectories = false
            openPanel.canChooseFiles = true
            openPanel.allowedFileTypes = ["png","jpg","jpeg"]
            openPanel.begin { (result) -> Void in
                if result.rawValue == NSApplication.ModalResponse.OK.rawValue {
                    let selectedPath = openPanel.url!.path
                    print(selectedPath)
                    
                }
            }
        }
    }
}

在我显示所选图片的地方下方:

struct NewPost: View {
    
    @Environment(\.presentationMode) var presentationMode
    
    var postToEdit: Item?
    var viewContext: NSManagedObjectContext
    ...
    @State var fileUrl: URL?
    
    var header: String {
        postToEdit == nil ? "Create Post" : "Edit Post"
    }
    
    
    var body: some View {

    ...Form Code

    // Displaying Image if its selected...
                
Section(header: Text("Picture").foregroundColor(Color("blue")).font(.title2)) {
                        
if let fileUrl = fileUrl, let img = NSImage(contentsOf: fileUrl) {
                            
    Image(nsImage: img)
        .resizable()
        .scaledToFill()
        .clipShape(Circle())
        .overlay(Circle().stroke(Color.white, lineWidth: 1))
        .opacity(1)
        .frame(minWidth: 120, maxWidth: 120, minHeight: 120, maxHeight: 120)
                            
     }
                        
 if pic.count != 0 {
                            
          Image(nsImage: NSImage(data: pic)!)
              .resizable()
              .scaledToFill()
              .clipShape(Circle())
              .overlay(Circle().stroke(Color.white, lineWidth: 1))
              .opacity(1)
              .frame(minWidth: 120, maxWidth: 120, minHeight: 120, maxHeight: 120)
         }
     }
     .cornerRadius(10)

根据下面的响应更新了上面的代码。

提前致谢。

您可以使用 Binding 将数据从 child 视图传递回 parent:

struct FileView: View {
    @Binding var fileUrl : URL?
    
    var body: some View {
        Button("Select File") {
            let openPanel = NSOpenPanel()
            openPanel.prompt = "Select File"
            openPanel.allowsMultipleSelection = false
            openPanel.canChooseDirectories = false
            openPanel.canCreateDirectories = false
            openPanel.canChooseFiles = true
            openPanel.allowedFileTypes = ["png","jpg","jpeg"]
            openPanel.begin { (result) -> Void in
                if result.rawValue == NSApplication.ModalResponse.OK.rawValue {
                    fileUrl = openPanel.url
                }
            }
        }
    }
}

struct ContentView: View {
    @State var fileUrl: URL?
    
    var body: some View {
        VStack {
            FileView(fileUrl: $fileUrl)
            if let fileUrl = fileUrl, let image =  NSImage(contentsOf: fileUrl) {
                Image(nsImage: image)
            }
        }
    }
}

请注意,在 child 中,它是 @Binding,但在 parent 中,它是 @State

更新版本,使用Data:

struct FileView: View {
    @Binding var fileData : Data?
    
    var body: some View {
        Button("Select File") {
            let openPanel = NSOpenPanel()
            openPanel.prompt = "Select File"
            openPanel.allowsMultipleSelection = false
            openPanel.canChooseDirectories = false
            openPanel.canCreateDirectories = false
            openPanel.canChooseFiles = true
            openPanel.allowedFileTypes = ["png","jpg","jpeg"]
            openPanel.begin { (result) -> Void in
                if result.rawValue == NSApplication.ModalResponse.OK.rawValue {
                    guard let url = openPanel.url, let data = try? Data(contentsOf: url) else {
                        //handle errors here
                        return
                    }
                    fileData = data
                }
            }
        }
    }
}

struct ContentView: View {
    @State var fileData: Data?
    
    var body: some View {
        VStack {
            FileView(fileData: $fileData)
            if let fileData = fileData, let image =  NSImage(data: fileData) {
                Image(nsImage: image)
            }
        }
    }
}

注意:显然,在这个例子中,没有对无法读取 URL 或任何东西进行任何错误处理