我正在尝试向我的SwiftUI Mac应用程序添加一个“拖放”手势/函数。
我想把文件从我的系统/桌面放到我的应用程序中。我发现它属于普通的Swift公司。我现在正试着用SwiftUI来做这个。
我在onDrop()中为视图找到了一个SwiftUI函数。但是,看起来这只适用于我的应用程序中的内部手势。我想从外面拖文件。
在Swift中,您需要注册您的NSView,用于拖动类型。
registerForDraggedTypes([kUTTypeFileURL,kUTTypeImage])我想创建一个NSViewRepresentable并将其包装到我的SwiftUI视图中。
这是我想出的代码,但是我不能调用registerForDraggedTyped。
final class DragDropView: NSViewRepresentable {
func makeNSView(context: NSViewRepresentableContext<DragDropView>) -> NSView {
let view = NSView()
view.registerForDraggedTypes([NSPasteboard.PasteboardType.pdf, NSPasteboard.PasteboardType.png])
return view
}
func updateNSView(_ nsView: NSView, context: NSViewRepresentableContext<DragDropView>) {
}在SwiftUI中有更简单的解决方案吗?我很想使用这个onDrop()函数,但是这并不适用于外部文件,对吗?
发布于 2020-03-24 14:05:33
下面是一个拖放演示,用Xcode 11.4 / macOS 10.15.4进行测试。
初始image位于资产库上,接受从Finder/Desktop ( drop )到TextEdit (拖放)的文件url (仅为简单起见),并为TIFF表示拖动寄存器。
struct TestImageDragDrop: View {
@State var image = NSImage(named: "image")
@State private var dragOver = false
var body: some View {
Image(nsImage: image ?? NSImage())
.onDrop(of: ["public.file-url"], isTargeted: $dragOver) { providers -> Bool in
providers.first?.loadDataRepresentation(forTypeIdentifier: "public.file-url", completionHandler: { (data, error) in
if let data = data, let path = NSString(data: data, encoding: 4), let url = URL(string: path as String) {
let image = NSImage(contentsOf: url)
DispatchQueue.main.async {
self.image = image
}
}
})
return true
}
.onDrag {
let data = self.image?.tiffRepresentation
let provider = NSItemProvider(item: data as NSSecureCoding?, typeIdentifier: kUTTypeTIFF as String)
provider.previewImageHandler = { (handler, _, _) -> Void in
handler?(data as NSSecureCoding?, nil)
}
return provider
}
.border(dragOver ? Color.red : Color.clear)
}
}发布于 2020-07-03 06:12:44
正如OP所指出的,对于Mac应用程序,这是仅限。
如果你想
然后尝试以下操作(从此视图拖动图像不包括在内)。
XCode 11+ / SwiftUI 1.0+ / Swift 5:
从Finder处打开所需的分机:
extension NSOpenPanel {
static func openImage(completion: @escaping (_ result: Result<NSImage, Error>) -> ()) {
let panel = NSOpenPanel()
panel.allowsMultipleSelection = false
panel.canChooseFiles = true
panel.canChooseDirectories = false
panel.allowedFileTypes = ["jpg", "jpeg", "png", "heic"]
panel.canChooseFiles = true
panel.begin { (result) in
if result == .OK,
let url = panel.urls.first,
let image = NSImage(contentsOf: url) {
completion(.success(image))
} else {
completion(.failure(
NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to get file location"])
))
}
}
}
}SwiftUI视图
struct InputView: View {
@Binding var image: NSImage?
var body: some View {
VStack(spacing: 16) {
HStack {
Text("Input Image (PNG,JPG,JPEG,HEIC)")
Button(action: selectFile) {
Text("From Finder")
}
}
InputImageView(image: self.$image)
}
}
private func selectFile() {
NSOpenPanel.openImage { (result) in
if case let .success(image) = result {
self.image = image
}
}
}
}
struct InputImageView: View {
@Binding var image: NSImage?
var body: some View {
ZStack {
if self.image != nil {
Image(nsImage: self.image!)
.resizable()
.aspectRatio(contentMode: .fit)
} else {
Text("Drag and drop image file")
.frame(width: 320)
}
}
.frame(height: 320)
.background(Color.black.opacity(0.5))
.cornerRadius(8)
.onDrop(of: ["public.url","public.file-url"], isTargeted: nil) { (items) -> Bool in
if let item = items.first {
if let identifier = item.registeredTypeIdentifiers.first {
print("onDrop with identifier = \(identifier)")
if identifier == "public.url" || identifier == "public.file-url" {
item.loadItem(forTypeIdentifier: identifier, options: nil) { (urlData, error) in
DispatchQueue.main.async {
if let urlData = urlData as? Data {
let urll = NSURL(absoluteURLWithDataRepresentation: urlData, relativeTo: nil) as URL
if let img = NSImage(contentsOf: urll) {
self.image = img
print("got it")
}
}
}
}
}
}
return true
} else { print("item not here") return false }
}
}
}注意:不需要使用"public.image“标识符。
如果需要作为PNG数据的结果(我确实上传到Firebase存储),可以选择扩展:
extension NSBitmapImageRep {
var png: Data? { representation(using: .png, properties: [.compressionFactor:0.05]) }
}
extension Data {
var bitmap: NSBitmapImageRep? { NSBitmapImageRep(data: self) }
}
extension NSImage {
var png: Data? { tiffRepresentation?.bitmap?.png }
}
// usage
let image = NSImage(...)
if let data = image.png {
// do something further with the data
}发布于 2020-03-24 12:53:19
你不能用onDrop(of:isTargeted:perform:)吗?可以在of参数中传递受支持类型的数组。
https://stackoverflow.com/questions/60831260
复制相似问题