如何在 SwiftUI 中处理拖动到停靠栏图标上的操作?

2024-02-10

我已经设置了一个 SwiftUI 应用程序,它似乎接受拖放到停靠图标上的图像,但我无法弄清楚在应用程序代码中处理拖放图像的位置。

如何处理将图像(或任何特定文件)拖放到 SwiftUI 应用程序的停靠图标上?

背景

对于使用 NSApplication 的旧式 Swift 代码,处理应用程序停靠图标上的文件拖放可以通过两个步骤完成:

  1. 在 Info.plist 的 CFBundleDocumentTypes 中注册您想要接受的类型。
  2. 实施应用程序:打开文件: https://developer.apple.com/documentation/appkit/nsapplicationdelegate#//apple_ref/doc/uid/TP40008592-CH1-SW29(可能还有 application:openFiles:) 在你的 NSApplicationDelegate 上。

这被简洁地记录在一个单独的问题 https://stackoverflow.com/questions/2489961/dropping-files-onto-dock-icon-in-cocoa.

在 Swift UI 中创建应用程序委托(不起作用)

不过,SwiftUI 应用程序默认不提供应用程序委托。要实现这些功能,您必须做一些额外的工作 https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-an-appdelegate-to-a-swiftui-app:

  1. 创建一个类来实现NSObject and NSApplicationDelegate (or UIApplicationDelegate):

    // or NSApplicationDelegate
    class AppDelegate: NSObject, UIApplicationDelegate {
       // ...
    }
    
  2. In your @main App实现,设置委托:

    ... : App {
        // or @NSApplicationDelegateAdaptor
        @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    

您现在可以实现应用程序委托方法!例如,这将在您的应用程序启动时打印:

func applicationWillFinishLaunching(_ notification: Notification) {
    print("App Delegate loaded!")
}

But实现 openFile 函数不起作用:

func application(_ sender: NSApplication, openFile filename: String) -> Bool {
    print("test", filename)
    return false
 }
    
func application(_ sender: NSApplication, openFiles filenames: [String]) {
     print("another test", filenames)
}

将文件拖到应用程序上时,这些都不会打印出来。

现场代表?

这似乎是将 AppDelegate 功能分离到 SceneDelegate 中的一些工作的结果:

对于那些可能对此感到头疼的人来说,由于 appdelegate 功能的分离,现在在 scenedelegate 中调用等效的功能。等效的函数是 scene(_ scene: openURLContexts:)。我还没有研究过是否可以“选择退出”这一点,但就我的目的而言,没有理由不采用新行为

— m_bedwell 上应用程序(打开:选项:)没有被调用 https://developer.apple.com/forums/thread/119493(强调已添加)

但是我们的代码没有明显的方法来访问 SceneDelegate(这甚至可能不适用于 macOS?)。有一个有希望提出类似的问题 https://stackoverflow.com/questions/56498099/difference-between-scenedelegate-and-appdelegate.

有没有更好的办法?


有一种非常简单的方法可以处理 SwiftUI 中 Dock 图标上的拖放!

  1. 更新您的 Info.plist 以表明您的应用程序支持您想要的文件类型(就像在旧应用程序中一样):

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <!-- ... -->
        <key>CFBundleTypeName</key>
        <string>Image files</string>
        <key>CFBundleTypeRole</key>
        <string>Viewer</string>
        <key>LSHandlerRank</key>
        <string>Default</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>public.image</string>
        </array>
    </dict>
    </plist>
    
  2. In your body在你的App, use 打开URL https://developer.apple.com/documentation/swiftui/outlinesubgroupchildren/onopenurl%28perform:%29:

    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { (url) in
                    // Handle url here
                }
        }
    }
    

— ianivs (如何使用新的 SwiftUI @main 启动处理 URL 回调? https://developer.apple.com/forums/thread/651234)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 SwiftUI 中处理拖动到停靠栏图标上的操作? 的相关文章

随机推荐