如何在SwiftUI中处理拖到dock图标上的操作



我已经设置了一个SwiftUI应用程序,它似乎可以接受放在dock图标上的图像,但我不知道在应用程序代码中在哪里处理掉的图像。

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

背景

对于使用NSApplication的老式Swift代码,可以通过两个步骤来处理应用程序停靠图标上的文件丢弃:

  1. 在Info.plist中的CFBundleDocumentTypes中注册要接受的类型
  2. 在NSApplicationDelegate上实现应用程序:openFile:(可能还有应用程序:openFiles:(

这在另一个问题中有简明扼要的记录。

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

不过,SwiftUI应用程序默认情况下不提供应用程序委派。要实现这些功能,您必须做一些额外的工作:

  1. 创建一个实现NSObjectNSApplicationDelegate(或UIApplicationDelegate(的类:

    // or NSApplicationDelegate
    class AppDelegate: NSObject, UIApplicationDelegate {
    // ...
    }
    
  2. @mainApp实现中,设置代理:

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

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

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

但是实现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功能分离到SceneDelegates:的一些工作的结果

对于那些可能会为此感到头疼的人,由于appdelegate的功能分离,现在在场景中调用了等效的功能等价的ish函数是scene(_scene:openURLContext:(。我还没有研究是否有可能"选择退出",但就我的目的而言,没有理由不采用新的行为

应用程序上的m_bedwell(打开:选项:(未被调用(添加了强调(

但是,我们的代码没有明显的方法访问SceneDelegate(这甚至可能不适用于macOS?(。还有一个很有希望的类似问题。

有更好的方法吗?

在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. bodyApp中,使用onOpenURL:

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

--ianivs(如何使用新的SwiftUI@main启动处理URL回调?(

最新更新