我正在嘗試使用用 SwiftUI 撰寫的視圖作為我的附件視圖,NSSavePanel但我很難讓它正常作業。
這是我的 SwiftUI 視圖的實作:
struct ExportAccessoryView: View {
enum ExportFileType: String, Identifiable {
// ... enum declaration
}
@State var selectedExportFileType: ExportFileType = .png
@State var resolution = 256.0
@Binding var selectedFileTypeBinding: ExportFileType
@Binding var resolutionBinding: Double
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Picker(selection: $selectedExportFileType, label: Text("Format:")) {
Text("PDF").tag(ExportFileType.pdf)
// ... other items
}
.frame(width: 170)
.padding(.leading, 21)
if [ExportFileType.png, ExportFileType.jpeg, ExportFileType.tiff].contains(selectedExportFileType) {
HStack {
Slider(value: $resolution, in: 128...1024,
label: { Text("Resolution:") })
.frame(width: 200)
Text("\(Int(resolution))")
.frame(width: 40, alignment: .leading)
.padding(.leading, 5)
}
}
}
.padding(10)
.onChange(of: selectedExportFileType) { newValue in
self.selectedFileTypeBinding = newValue
}
.onChange(of: resolution) { newValue in
self.resolutionBinding = newValue
}
}
}
這是我實作保存面板的方式:
class DocumentWindow: NSWindowController {
var exportFileType: ExportAccessoryView.ExportFileType = .pdf
var resolution = 256.0
lazy var exportPanel: NSSavePanel = {
let savePanel = NSSavePanel()
savePanel.message = "Specify where and how you wish to export..."
savePanel.nameFieldLabel = "Export As:"
savePanel.canCreateDirectories = true
savePanel.isExtensionHidden = false
savePanel.showsTagField = true
let fileTypeBinding = Binding {
return self.exportFileType
} set: { newValue in
self.exportFileType = newValue
// update file extension
self.exportPanel.allowedContentTypes = [UTType(newValue.rawValue)!]
}
let resolutionBinding = Binding {
return self.resolution
} set: { newValue in
self.resolution = newValue
}
let accessoryView = ExportAccessoryView(selectedFileTypeBinding: fileTypeBinding,
resolutionBinding: resolutionBinding)
let exportAccessoryView = NSHostingController(rootView: accessoryView)
savePanel.accessoryView = exportAccessoryView.view
savePanel.allowedContentTypes = [UTType(self.exportFileType.rawValue)!]
return savePanel
}()
}
保存面板通過呼叫來呈現beginSheetModal(for:completionHandler:)。
它顯示沒有問題,但附件視圖表現出一些奇怪的行為:它似乎在隨機做自己的事情(我尋找模式但我沒有這樣做)。
有時它可以正常作業,有時它變得不可點擊(但該功能仍然可以通過使用 的開關控制來訪問TAB)。對齊方式總是與我上次展開/折疊或打開/關閉面板時不同:有時它左對齊,有時它居中(即使我已明確選擇.leading對齊)。
我完全不知道發生了什么。我不知道這是否是 SwiftUI AppKit 的問題,還是我做錯了,這很可能是因為我是 SwiftUI 的新手。我應該怎么做才能讓它正常作業?
uj5u.com熱心網友回復:
我記得以前我使用 XIB 實作附件視圖的時候:我曾經將控制元件嵌入到 an 中NSView,然后設定約束以使其作業。所以我在這里應用了相同的想法,將NSHostingView's嵌入到view自定義中NSView,并在對其進行了一些調整之后,我讓它作業了:
lazy var exportPanel: NSSavePanel = {
// ... setting up save panel
// instantiate SwiftUI view and its hosting controller
let accessoryView = ExportAccessoryView(selectedFileTypeBinding: fileTypeBinding,
resolutionBinding: resolutionBinding)
let exportAccessoryView = NSHostingController(rootView: accessoryView)
// embed the SwiftUI in a custom view
let customView = NSView(frame: NSRect(x: 0, y: 0, width: 300, height: 60))
customView.addSubview(exportAccessoryView.view)
// use my own constraints
exportAccessoryView.view.translatesAutoresizingMaskIntoConstraints = false
// top and bottom clipped to custom view
exportAccessoryView.view.topAnchor.constraint(equalTo: customView.topAnchor).isActive = true
exportAccessoryView.view.bottomAnchor.constraint(equalTo: customView.bottomAnchor).isActive = true
// leading and trailing spaces can stretch as far as they need to be, hence ≥0
exportAccessoryView.view.leadingAnchor.constraint(greaterThanOrEqualTo: customView.leadingAnchor).isActive = true
exportAccessoryView.view.trailingAnchor.constraint(greaterThanOrEqualTo: customView.trailingAnchor).isActive = true
// center the SwiftUI view horizontal within custom view
exportAccessoryView.view.centerXAnchor.constraint(equalTo: customView.centerXAnchor).isActive = true
// usually fixed width and height
// can be flexible when SwiftUI view is dynamic
exportAccessoryView.view.widthAnchor.constraint(equalToConstant: customView.frame.width).isActive = true
exportAccessoryView.view.heightAnchor.constraint(greaterThanOrEqualToConstant: customView.frame.height).isActive = true
savePanel.accessoryView = customView
// ... additional setup
return savePanel
}()
現在它可以按預期完美運行。不知道這是否是實作這種集成的“正確方法”。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/504419.html
下一篇:嘗試讀取MacOS剪貼板內容
