hschaeufler
hschaeufler

Reputation: 186

How to include Notification Scene in WatchOS-App? Option is Missing in XCode V 14.2

I am new to SwiftUI development so I did the official SwiftUI-Landmark tutorial. The chapter Creating a watchOS App says that you should check the checkbox "Include Notification Scene" in the template when adding the WatchOSApp target. However, in my Xcode V 14.2 there is no such checkbox. Am I doing something wrong? Is there a possibility to add this scene afterwards?

This are the options i can choose: Creating WatchOs App

I also posted this Question in the Apple Developer Forum. But till now nobody answered.

Edit Jan 2024

Many thanks to everyone for their answers. The Landmark tutorial has now also been updated and no longer requires the "Include Notification Scene" checkbox.

Upvotes: 7

Views: 1057

Answers (3)

Jonas Cerqueira
Jonas Cerqueira

Reputation: 370

Sadly I Could not make it work on Watch Simulator using the Dynamic Notification Scheme on Xcode 14.3.1 and watchOS 9.4.

But there is another way to test your custom Custom Notification Interface.

1 Ask Permission

First you must ask permission for sending notifications:

LandmarksApp.swift

import SwiftUI
import UserNotifications

@main
struct LandmarksApp: App {
    @StateObject private var modelData = ModelData()
    let center = UNUserNotificationCenter.current()
    
    init() {
        center.requestAuthorization(options: [.alert, .sound, .badge], completionHandler: { (granted, error) in
            if let error: Error {
                print(error)
            }
        })
    }
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(modelData)
        }
#if os(watchOS)
        WKNotificationScene(controller: NotificationController.self, category: "LandmarkNear")
#endif
    }
}

2 Authorize your App

build and run your landmark watchKit app on the simulator and accept the request by tapping in Allow:

Authorization message

3 Update PushNotificationPayload

We need to identify our watch app by adding its product bundle identifier, on PushNotificationPayload.apns, add this line with your watch app bundle name"Simulator Target Bundle": "<watchOS App Bundle ID>",

PushNotificationPayload.apns

{
    "aps": {
        "alert": {
            "title": "Silver Salmon Creek",
            "body": "You are within 5 miles of Silver Salmon Creek."
        },
        "category": "LandmarkNear",
        "thread-id": "5280"
    },
    
    "landmarkIndex": 1,
    
    "Simulator Target Bundle": "com.example.Landmarks.watchkitapp",
    
    "WatchKit Simulator Actions": [
        {
            "title": "First Button",
            "identifier": "firstButtonAction"
        }
    ],
    
    "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App."
}

4 Send it

Now to send the notification, drag the updated PushNotificationPayload.apns file and drop it into your watch simulator window (You can do it inside Xcode):

dragging and dropping the file

That's it! Cheers!

Upvotes: 4

Artem M
Artem M

Reputation: 1036

The checkbox is in fact missing in Xcode 14+ (as of Jan 2023). In Xcode 13 it creates additional files when you selected the checkbox, these files are: NotificationView.swift, NotificationController.swift, ComplicationController.swift, PushNotificationPayload.apns, as well as two schemes to launch the notification and the complication.

Fortunately, you don't need complications to complete the tutorial, so you have only to create 3 files and one scheme before moving on to the Section 5 — Create a Custom Notification Interface.

I provided the detailed explanation with screenshots in the blog post, but here is a short description of what you have to do:

Step 1: Create a NotificationView.swift

Create a new SwiftUI View file in the WatchLandmarks Watch App folder. Name it NotificationView.swift:

import SwiftUI

struct NotificationView: View {
    var body: some View {
        Text("Hello, World!")
    }
}

struct NotificationView_Previews: PreviewProvider {
    static var previews: some View {
        NotificationView()
    }
}

Do not be confused about its stub content. The file will be modified during the next section of the Apple tutorial. For now you just need these files in a state they were created in Xcode 13.

Step 2: Create a NotificationController.swift

Create a Swift file called NotificationController.swift in the same folder:

import WatchKit
import SwiftUI
import UserNotifications

class NotificationController: WKUserNotificationHostingController<NotificationView> {

    override var body: NotificationView {
        return NotificationView()
    }

    override func willActivate() {
        // This method is called when watch view controller is about to be visible to user
        super.willActivate()
    }

    override func didDeactivate() {
        // This method is called when watch view controller is no longer visible
        super.didDeactivate()
    }

    override func didReceive(_ notification: UNNotification) {
        // This method is called when a notification needs to be presented.
        // Implement it if you use a dynamic notification interface.
        // Populate your dynamic notification interface as quickly as possible.
    }
}

Step 3: Create a PushNotificationPayload.apns

In the same folder, create an Empty file (bottom of the new file screen) and call it PushNotificationPayload.apns. Paste its contents:

{
    "aps": {
        "alert": {
            "body": "Test message",
            "title": "Optional title",
            "subtitle": "Optional subtitle"
        },
        "category": "myCategory",
        "thread-id": "5280"
    },
    
    "WatchKit Simulator Actions": [
        {
            "title": "First Button",
            "identifier": "firstButtonAction"
        }
    ],
    
    "customKey": "Use this file to define a testing payload for your notifications. The aps dictionary specifies the category, alert text and title. The WatchKit Simulator Actions array can provide info for one or more action buttons in addition to the standard Dismiss button. Any other top level keys are custom payload. If you have multiple such JSON files in your project, you'll be able to select them when choosing to debug the notification interface of your Watch App."
}

Step 4: Create a Notification scheme

Now you need to create a scheme to run a notification with a custom view you just created.

  • Click the scheme selector in the Xcode toolbar and select New Scheme… in the dropdown.
  • Select the Watch App as the target and add (Notification) to the scheme name for the sake of clarity. Click OK.
  • Click the schemes again, make sure the Notification scheme is selected, and click Edit Scheme.
  • In the popup, select the Run row in the left panel, then change Watch Interface to Dynamic Notification. After this, the Notification Payload field should be automatically switched to PushNotificationPayload.apns.
  • Click Close.

From this state, you can easily continue with the tutorial.

Upvotes: 8

Yev M
Yev M

Reputation: 23

Only if you want to customize that scene. Otherwise watchOS will just display your notifications in a default interface.

When you create a project, you will see a generic ContentView file with your first view and a file named after your app that displays ContentView in a window in a scene.

You can just create a new scene and window for notifications here and customize the view in a separate file (to stay organized) just like for your application.

Upvotes: 2

Related Questions