onmyway133 / blog

🍁 What you don't know is what you haven't learned
https://onmyway133.com/
MIT License
676 stars 33 forks source link

How to open app with Control Widget on iOS 18 #983

Open onmyway133 opened 4 weeks ago

onmyway133 commented 4 weeks ago

In iOS 18, we can make Control Widget in Widget extension

import WidgetKit
import SwiftUI

@available(iOS 18.0, *)
struct BookControlWidget: ControlWidget {
    var body: some ControlWidgetConfiguration {
        StaticControlConfiguration(kind: "Book") {
            ControlWidgetButton(action: BookIntent()) {
                Label("Book", systemImage: "airplane")
            }
        }
        .displayName("Book")
    }
}
import AppIntents

@available(iOS 18.0, *)
struct BookIntent: AppIntent {
    static let title: LocalizedStringResource = "Book"

    static var openAppWhenRun = true
    static var isDiscoverable = true

    func perform() async throws -> some IntentResult & OpensIntent {
        let url = URL(string: "myapp://book")!
        return .result(opensIntent: OpenURLIntent(url))
    }
}

From Creating controls to perform actions across the system

The system requires the Target Membership of the app intent to be set to both the app and the widget extension to open the app

We can open our app with OpenIntent

Set your control’s action to an app intent that conforms to OpenIntent to open your app when someone uses a control. Using OpenIntent allows you to take someone to a specific area of your app when a control performs its action.

image

The system requires the Target Membership of the app intent to be set to both the app and the widget extension to open the app.

import AppIntents

struct LaunchAppIntent: OpenIntent {
    static var title: LocalizedStringResource = "Launch App"
    @Parameter(title: "Target")
    var target: LaunchAppEnum
}

Another way is to use OpenURLIntent from iOS 18 to open universal link

Return an OpenURLIntent as the IntentResult of another app intent’s [perform()](https://developer.apple.com/documentation/appintents/appintent/perform()-2vmgc) method or use place the intent on a button that appears on an interactive widget or Live Activity.

image

Note that you need to use a universal link for your URL representation, you can’t use a custom URL scheme.

import AppIntents

@available(iOS 18.0, *)
struct Bookntent: AppIntent {
    static let title: LocalizedStringResource = "Book"

    static var openAppWhenRun = true
    static var isDiscoverable = true

    func perform() async throws -> some IntentResult & OpensIntent {
        let url = URL(string: "https://myapp.com/book")!
        return .result(opensIntent: OpenURLIntent(url))
    }
}

Read more

dota2AndTI commented 1 day ago

func perform() async throws -> some IntentResult & OpensIntent { let url = URL(string: "myapp://book")! return .result(opensIntent: OpenURLIntent(url)) } 这种方式iOS18不能跳转APP