SwiftUI macOS onDrop 简单文本总是失败
SwiftUI macOS onDrop simple text always fails
尝试实现文本文件的简单拖放:
struct ContentView: View {
@State private var drag = false
var body: some View {
Text("Hello, world!")
.frame(width: 300, height: 300)
.onDrop(of: [.url], isTargeted: $drag) { (providers, location) in
print("Can load", providers.first?.canLoadObject(ofClass: NSURL.self) == true) // Always false
providers.first?.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil, completionHandler: { secureCoding, error in
if let error = error {
print(error) // Cannot load representation of type ...
}
if let item = secureCoding as? Data { // Always nil
print("got data")
}
})
return true
}
}
}
尝试同时播放已删除文件的 UTType (public.url、public.data) 和 loadItem(forTypeIdentifier)
。
我没有尝试过。找到了类似的问题,但它们没有用,而且答案看起来已经过时了。
我有旧的 Cocoa 代码,registerForDraggedTypes
,这看起来简单多了,如果它有效的话..
刚刚使用纯 .txt 文件进行了修改和测试。 Xcode 13.3 / macOS 12.3.1
@State private var text = "Drop Here"
var body: some View {
Text(text)
.frame(width: 200, height: 200).border(.red)
.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) {
if let value = try? String(contentsOf: url, encoding: .utf8) {
DispatchQueue.main.async {
self.text = value
}
}
}
})
return true
}
*注意:我不记得确切的位置,但我在 Apple 的文档中遇到过我们必须为特定 use-cases 使用具体的 UTType 而不是通用的,即。 fileURL 实际上是 URL 但要匹配它必须准确指定!
我想 post 我自己的答案,只是为了指出陷阱。感谢@Asperi,我得到了一个工作样本。
.onDrop(of: [.fileURL]
,需要是UTType.fileURL
(或public.file-url
),而不是UTType.url
。
- 我正在使用
providers.first?.loadItem(forTypeIdentifier:...
,需要 loadDataRepresentation(forTypeIdentifier:...
- 读取数据:
使用 let path = String(data: data, encoding: .utf8)
有效。下一步很重要,我需要使用 URL(string:)
。不是 URL(fileURLWithPath:)
使用 URL(fileURLWithPath:)
会产生类似于 URL 且具有安全范围的内容。
其他小说明:
使用 let path = String(data: data, encoding: .utf8)
有效,不需要 NNString
.
使用 UTType.fileURL
(UTType.fileURL.identifier
用于 String
)也可以,无需硬编码 "public.file-url"
尝试实现文本文件的简单拖放:
struct ContentView: View {
@State private var drag = false
var body: some View {
Text("Hello, world!")
.frame(width: 300, height: 300)
.onDrop(of: [.url], isTargeted: $drag) { (providers, location) in
print("Can load", providers.first?.canLoadObject(ofClass: NSURL.self) == true) // Always false
providers.first?.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil, completionHandler: { secureCoding, error in
if let error = error {
print(error) // Cannot load representation of type ...
}
if let item = secureCoding as? Data { // Always nil
print("got data")
}
})
return true
}
}
}
尝试同时播放已删除文件的 UTType (public.url、public.data) 和 loadItem(forTypeIdentifier)
。
我没有尝试过。找到了类似的问题,但它们没有用,而且答案看起来已经过时了。
我有旧的 Cocoa 代码,registerForDraggedTypes
,这看起来简单多了,如果它有效的话..
刚刚使用纯 .txt 文件进行了修改和测试。 Xcode 13.3 / macOS 12.3.1
@State private var text = "Drop Here"
var body: some View {
Text(text)
.frame(width: 200, height: 200).border(.red)
.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) {
if let value = try? String(contentsOf: url, encoding: .utf8) {
DispatchQueue.main.async {
self.text = value
}
}
}
})
return true
}
*注意:我不记得确切的位置,但我在 Apple 的文档中遇到过我们必须为特定 use-cases 使用具体的 UTType 而不是通用的,即。 fileURL 实际上是 URL 但要匹配它必须准确指定!
我想 post 我自己的答案,只是为了指出陷阱。感谢@Asperi,我得到了一个工作样本。
.onDrop(of: [.fileURL]
,需要是UTType.fileURL
(或public.file-url
),而不是UTType.url
。- 我正在使用
providers.first?.loadItem(forTypeIdentifier:...
,需要loadDataRepresentation(forTypeIdentifier:...
- 读取数据:
使用let path = String(data: data, encoding: .utf8)
有效。下一步很重要,我需要使用URL(string:)
。不是URL(fileURLWithPath:)
使用URL(fileURLWithPath:)
会产生类似于 URL 且具有安全范围的内容。
其他小说明:
使用 let path = String(data: data, encoding: .utf8)
有效,不需要 NNString
.
使用 UTType.fileURL
(UTType.fileURL.identifier
用于 String
)也可以,无需硬编码 "public.file-url"