【问题标题】:How do I handle dragging onto the dock icon in SwiftUI?如何处理拖到 SwiftUI 中的停靠图标上?
【发布时间】:2021-03-26 12:38:24
【问题描述】:

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

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

背景

使用使用 NSApplication 的旧式 Swift 代码,处理应用程序停靠图标上的文件删除可以分两步完成:

  1. 在 Info.plist 的 CFBundleDocumentTypes 中注册要接受的类型。
  2. 在您的 NSApplicationDelegate 上实现 application:openFile:(可能还有 application:openFiles:)。

这在a separate question 中有简要说明。

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

不过,SwiftUI 应用默认不提供应用委托。要实现这些功能,你必须do some additional work

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

    // or NSApplicationDelegate
    class AppDelegate: NSObject, UIApplicationDelegate {
       // ...
    }
    
  2. 在您的 @main App 实现中,设置委托:

    ... : 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 的功能分离,现在在 scenedelegate 中调用等效功能。等效功能是 scene(_ scene: openURLContexts: )。我还没有研究过是否可以“选择退出”,但出于我的目的,没有理由不采用新的行为

application(open: options:) not being called 上的 m_bedwell(已添加重点)

但是没有明显的方法可以访问我们的代码的 SceneDelegate(这甚至可能不适用于 macOS?)。有一个promising similar question

有没有更好的办法?

【问题讨论】:

    标签: swift macos swiftui


    【解决方案1】:

    有一种非常简单的方法可以在 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. 在您的body 中,在您的App 中,使用onOpenURL

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

    ——ianivs (How to handle URL callbacks with new SwiftUI @main startup?)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-16
      • 1970-01-01
      • 2011-10-08
      • 1970-01-01
      • 2018-06-02
      • 1970-01-01
      • 2011-06-10
      相关资源
      最近更新 更多