Create Dynamic Notifications on Apple Watch with SwiftUI And WatchKit App Delegate

Set Up an Apple Watch project:

Set Up Local Notifications:

import SwiftUIimport UserNotificationsstruct ContentView: View {var body: some View {VStack{Button("Request permission"){UNUserNotificationCenter.current().requestAuthorization(options: [.alert,.sound,.badge]) { (success, error) inif success{print("All set")} else if let error = error {print(error.localizedDescription)}}}Button("Schedule Notification"){let content = UNMutableNotificationContent()content.title = "Drink some milk!"content.subtitle = "you have 10 sec"content.sound = .defaultcontent.categoryIdentifier = "myCategory"let category = UNNotificationCategory(identifier: "myCategory", actions: [], intentIdentifiers: [], options: [])UNUserNotificationCenter.current().setNotificationCategories([category])let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 10, repeats: false)let request = UNNotificationRequest(identifier: "milk", content: content, trigger: trigger)UNUserNotificationCenter.current().add(request) { (error) inif let error = error{print(error.localizedDescription)}else{print("scheduled successfully")}}}}}}

Set Up Dynamic Views

import SwiftUIstruct NotificationView: View {@Environment(\.presentationMode) var presentationMode@State private var ringAnimation: CGFloat = 0@State private var counter = 10var count = 10var body: some View {VStack{Text("Drink some milk!").font(.subheadline)ZStack{//MARK: - Background CircleCircle().stroke(Color.white.opacity(0.1), style: StrokeStyle(lineWidth: 15))//MARK: - Progress CircleCircle().trim(from: ringAnimation, to: 1.0).stroke(LinearGradient(gradient: Gradient(colors: [Color( colorLiteral(red: 0.2588235438, green: 0.7568627596, blue: 0.9686274529, alpha: 1)), Color( colorLiteral(red: 0.2666666667, green: 0.8431372549, blue: 0.7137254902, alpha: 1))]), startPoint: .topTrailing, endPoint: .bottomLeading),style: StrokeStyle(lineWidth: 15, lineCap: .round)).rotationEffect(Angle(degrees: 90)).rotation3DEffect(Angle(degrees: 180), axis: (x: 1, y: 0, z: 0)).shadow(color: Color( colorLiteral(red: 0.2666666667, green: 0.8431372549, blue: 0.7137254902, alpha: 1)).opacity(0.3), radius: 3, x: 0, y: 3).animation(.easeInOut)//MARK: - PercentageText("🥛\n\(counter)").font(.title3).multilineTextAlignment(.center)}.padding().onAppear{updateRing()}.frame(minWidth: 100, idealWidth: 110, maxWidth: .infinity, minHeight: 100, idealHeight: 110, maxHeight: .infinity, alignment: .center)}}func updateRing(){if counter == 0 {self.presentationMode.wrappedValue.dismiss()ringAnimation = 10return}else{DispatchQueue.main.asyncAfter(deadline: (.now() + 1)) {ringAnimation += CGFloat(1) / CGFloat(count)counter -= 1updateRing()}}}}

Showing Dynamic Notifications

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store