iOS:在主屏幕上用力触摸应用程序时打开应用程序

问题描述 投票:0回答:1

我正在尝试使用最新版本的 Swift 创建一个 iOS 应用程序,用户可以在主屏幕上强制触摸我们的应用程序。然后可以选择打开苹果日历、笔记或地图。但是,当我们点击这些时,只会打开我们的应用程序,而不会打开相应的苹果应用程序。

这是我的 LauncherApp.swift 文件:

import SwiftUI
import UIKit

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    override init() {
        super.init()
        print("AppDelegate initialized")
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        print("Application did finish launching with options.")

        self.window = UIWindow()
        self.window?.rootViewController = UIHostingController(rootView: ContentView())
        self.window?.makeKeyAndVisible()

        if let shortcutItem = launchOptions?[.shortcutItem] as? UIApplicationShortcutItem {
            print("Launching from Quick Action: \(shortcutItem.type)")
            handleShortcutItem(shortcutItem)
            return false
        }

        return true
    }

    func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        print("Received a Quick Action while running: \(shortcutItem.type)")
        handleShortcutItem(shortcutItem)
        completionHandler(true)
    }


    private func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) {
        print("Handling Shortcut Item: \(shortcutItem.type)")

        switch shortcutItem.type {
        case "com.launcher.openMaps":
            print("Opening Maps...")
            openMaps()
        case "com.launcher.openCalendar":
            print("Opening Calendar...")
            openCalendar()
        case "com.launcher.openNotes":
            print("Opening Notes...")
            openNotes()
        default:
            print("Unhandled Shortcut Item: \(shortcutItem.type)")
        }
    }

    private func openMaps() {
        openApp(withURLScheme: "maps://")
    }

    private func openCalendar() {
        openApp(withURLScheme: "calshow://")
    }

    private func openNotes() {
        openApp(withURLScheme: "mobilenotes://")
    }

    private func openApp(withURLScheme urlScheme: String) {
        print("Attempting to open app with URL Scheme: \(urlScheme)")
        guard let url = URL(string: urlScheme) else {
            print("Invalid URL Scheme: \(urlScheme)")
            return
        }
        
        if UIApplication.shared.canOpenURL(url) {
            print("Opening app with URL Scheme: \(urlScheme)")
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        } else {
            print("Cannot open URL Scheme: \(urlScheme)")
        }
    }
}

@main
struct LauncherApp: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

这是我的 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>LSApplicationQueriesSchemes</key>
    <array>
        <string>maps</string>
        <string>mobilenotes</string>
        <string>calshow</string>
    </array>
    <key>UIApplicationShortcutItems</key>
    <array>
        <dict>
                    <key>UIApplicationShortcutItemIconType</key>
                    <string>UIApplicationShortcutIconTypeLocation</string>
                    <key>UIApplicationShortcutItemTitle</key>
                    <string>Open Maps</string>
                    <key>UIApplicationShortcutItemType</key>
                    <string>com.launcher.openMaps</string>
                </dict>
                <dict>
                    <key>UIApplicationShortcutItemIconType</key>
                    <string>UIApplicationShortcutIconTypeDate</string>
                    <key>UIApplicationShortcutItemTitle</key>
                    <string>Open Calendar</string>
                    <key>UIApplicationShortcutItemType</key>
                    <string>com.launcher.openCalendar</string>
                </dict>
                <dict>
                    <key>UIApplicationShortcutItemIconType</key>
                    <string>UIApplicationShortcutIconTypeCompose</string>
                    <key>UIApplicationShortcutItemTitle</key>
                    <string>Open Notes</string>
                    <key>UIApplicationShortcutItemType</key>
                    <string>com.launcher.openNotes</string>
                </dict>
            </array>
</dict>
</plist>

这里是 ContentView.swift,它可以完美地打开地图:

import SwiftUI

struct ContentView: View {
    var body: some View {
        Button("Test Open Maps") {
            openApp(withURLScheme: "maps://")
        }
    }

    func openApp(withURLScheme urlScheme: String) {
        guard let url = URL(string: urlScheme) else { return }
        if UIApplication.shared.canOpenURL(url) {
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

我是 iOS 开发新手,很抱歉只是转储代码,我已经尝试在模拟器和 iPhone 上进行测试,但它在两者上都不起作用。

我什至尝试询问多个人工智能服务,这就是我们现在的情况😅

ios swift iphone force-touch
1个回答
0
投票

在 iOS 13 及更高版本下运行时,App Delegate 不用于处理快捷方式。您现在需要处理场景委托中的快捷方式项目。

将名为 SceneDelegate.swift 的文件添加到您的项目中,其中包含以下内容:

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
        // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
        // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
        guard let _ = (scene as? UIWindowScene) else { return }

        // This will be true if a shortcut item is selected while the app is not running
        if let shortcutItem = connectionOptions.shortcutItem {
            _ = handleShortcutItem(shortcutItem)
        }
    }

    // Called if a shortcut item is selected while the app is already running
    func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
        let res = handleShortcutItem(shortcutItem)

        completionHandler(res)
    }

    private func handleShortcutItem(_ shortcutItem: UIApplicationShortcutItem) -> Bool {
        print("Handling Shortcut Item: \(shortcutItem.type)")

        switch shortcutItem.type {
            case "com.launcher.openMaps":
                print("Opening Maps...")
                openMaps()
                return true
            case "com.launcher.openCalendar":
                print("Opening Calendar...")
                openCalendar()
                return true
            case "com.launcher.openNotes":
                print("Opening Notes...")
                openNotes()
                return true
            default:
                print("Unhandled Shortcut Item: \(shortcutItem.type)")
        }

        return false
    }

    private func openMaps() {
        openApp(withURLScheme: "maps://")
    }

    private func openCalendar() {
        openApp(withURLScheme: "calshow://")
    }

    private func openNotes() {
        openApp(withURLScheme: "mobilenotes://")
    }

    private func openApp(withURLScheme urlScheme: String) {
        print("Attempting to open app with URL Scheme: \(urlScheme)")
        guard let url = URL(string: urlScheme) else {
            print("Invalid URL Scheme: \(urlScheme)")
            return
        }

        if UIApplication.shared.canOpenURL(url) {
            print("Opening app with URL Scheme: \(urlScheme)")
            UIApplication.shared.open(url, options: [:], completionHandler: nil)
        } else {
            print("Cannot open URL Scheme: \(urlScheme)")
        }
    }
}

在 AppDelegate.swift 中,删除用于处理快捷方式的私有函数(所有代码现在都在

SceneDelegate
中)。删除
performActionFor
应用程序委托方法,因为从 iOS 13 开始不再使用它。从
if let...
应用程序委托方法中删除
didFinishLaunchingWithOptions
块,因为它也在场景委托中处理。

对于 UIKit 应用程序来说,这就是所需要的。

对于 SwiftUI 应用程序,您需要将以下内容添加到您的

AppDelegate

// Setup the scene delegate
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
    let configuration = UISceneConfiguration(name: nil, sessionRole: connectingSceneSession.role)
    if connectingSceneSession.role == .windowApplication {
        configuration.delegateClass = SceneDelegate.self
    }

    return configuration
}

这让 SwiftUI 应用程序了解您的

SceneDelegate
类。

这些更改与 Info.plist 中快捷方式项目和 URL 方案查询的现有设置相结合,将使您的应用程序能够按预期响应快捷方式项目。

© www.soinside.com 2019 - 2024. All rights reserved.