SwiftUI九创建watchOS应用

代码下载

这篇教程让可以应用之前所学到的SwiftUI知识,把Landmarks应用从iOS平台迁移到watchOS平台上。在拷贝可以共用的数据和视图文件之前,需要先给项目中添加一个对应watchOS的Target编译目标。在所有 assets 就绪后,将自定义SwiftUI视图在watchOS上显示详细信息和列表视图。

按照下面的步骤构建工程,或者下载完成后的项目文件学习,项目文件。

添加一个watchOS编译目标

要创建一个watchOS应用,第一步是给项目添加一个对应watchOS平台的编译目标。Xcode在新增Target的同时,添加一个文件组和相应的文件到工程中,同时还会新增编译运行方案,指定应用要运行的平台或模拟器。

1、选择菜单 File->New->Target。当模板列表出现后,在 watchOS 选项卡下选择 App 模板,并点击下一步(Next)。

这个模板将一个新的watchOS应用程序添加到项目中。

2、在模板创建表中,输入 WatchLandmarks 作为产品名称,设置语言为Swift,用户界面为SwiftUI实现方式,并勾选 Watch App for Existing iOS App并选择 Landmarks (我在这里选的是之前的 InterfacingWithUIKit,因为不是以上面的项目文件中的工程为基础开发的),最后点击完成(Finish)。

3、如果Xcode提示激活watchOS平台编译运行方案,点击激活(Activate)。这会把编译运行方案从iOS平台切换到watchOS平台上来,这能够开始处理新目标。

4、在watchOS模拟器下拉列表中选择Apple Watch Series 9 (45mm)设备。

5、选择 WatchLandmarks Watch App Target 并导航到 Target 的 General 选项卡,下勾选 Supports Running Without iOS App Installation复选框。

在 Target 间共享文件

现在watchOS平台的编译目标(Target)已经创建好,为了避免重复工作,使用watchOS目标集,可以复用一些之前在iOS项目中的资源。地标的数据模型文件可以复用,一些资源文件以及一些两个平台下不需要修改就可以展示的视图文件也可复用。

首先,删除watchOS应用程序的入口点。不需要它,因为将重用在 Landmarks (我在这里是用InterfacingWithUIKit) App中定义的入口点。

1、在项目导航器中,删除 WatchLandmarks Watch App 文件夹中 的 WatchLandmarksApp 文件;当出现提示时,选择 “Move to trash”。

接下来,选择watchOS目标可以与现有iOS目标共享的所有文件,包括应用程序的入口点。

2、在Project navigator中,Command-click选择以下文件:LandmarksApp(我这里是InterfacingWithUIKitApp), LandmarkList, LandmarkRow, CircleImage, MapView。

第一个是共享应用程序定义。其他是应用程序可以在watchOS上显示的视图,无需更改。

3、继续 Command-clicking 添加以下模型文件:ModelData、Landmark、Hike、Profile。

这些项定义了应用程序的数据模型。不会使用模型的所有方面,但是需要所有的文件来成功编译这个应用。

4、完成command-clicking,添加由模型加载的资源文件:landmarkData、hikeData和Assets。

5、在文件检查器中,选择 Target Membership 部分中的 WatchLandmarks Watch App复选框。

这使得在前面步骤中选择的内容可用于 watchOS 应用程序。

最后,添加一个与已有的iOS应用图标相匹配的 watchOS 应用图标。

6、选择 WatchLandmarks Watch App 文件夹中的 Assets 文件,然后导航到空的AppIcon项。

7、将单个png文件从下载的项目的Resources文件夹中拖到现有的空AppIcon集中。

稍后,当创建通知时,系统会显示应用程序的图标,以帮助识别通知的来源。

创建详情视图

iOS编译目标下的资源可以在手表应用下使用,但需要创建一个专门适配手表尺寸的地标详情页来展示地标的具体信息。为了测试视图是否能适配手表展示,需要分别为最大尺寸和最小尺寸手表创建预览视图,并根据情况适当的调整圆形视图的布局来适应手表的界面大小。

1、添加一个新的自定义视图到 WatchLandmarks Watch App 文件夹,名为 LandmarkDetail.swift。

这个文件与iOS项目中的同名文件的区别在于它的目标成员——它只适用于WatchLandmarks Watch App目标。

2、将modelData、landmark和landmarkIndex属性添加到新的LandmarkDetail结构中,这些与在处理用户输入中添加的属性相同。

struct LandmarkDetail: View {
    @Environment(ModelData.self) var modelData
    var landmark: Landmark
    var landmarkIndex: Int {
        modelData.landmarks.firstIndex { $0.id == landmark.id } ?? 0
    }
}

3、在预览视图中,创建一个用户数据的实例,并给WatchLandmarkDetail结构体的初始化器中传入一个地标对象作为参数。这里需要把用户数据设置为视图的环境对象。

#Preview {
    let modelData = ModelData()
    return LandmarkDetail(landmark: modelData.landmarks[0]).environment(modelData)
}

4、设置设备选择器,使预览显示一个大手表。

5、从body()方法返回一个CircleImage视图。

这里重用了iOS项目中的CircleImage视图。因为创建了一个可调整大小的图像,所以调用scaledToFill()会调整圆圈的大小,使其填充显示器。

    var body: some View {
        CircleImage(image: landmark.image.resizable())
            .scaledToFill()
    }

6、改变设备选择器,使预览显示一个小手表。

通过对最大和最小的表盘进行测试,可以看到应用程序是如何适应显示器的。一如既往,应该在所有支持的设备尺寸上测试用户界面。

7、在VStack中嵌入圆形图像。在图像下方显示地标名称及其信息。正如所看到的,信息不太适合手表屏幕,但可以通过将VStack放置在滚动视图中来解决这个问题。

8、把VStack整体嵌入到一个ScrollView中,这就让视图获取了滚动查看的能力,但同时也引入了另一个问题:CircleImage现在扩展到完全尺寸,把其它元素挤到没有地方显示。所以需要缩放CircleImage,让圆形图片和地标名称可以在一屏内同时显示出来。

9、将scaleToFill()更改为scaleToFit()并添加padding。这将缩放圆形图像以匹配显示器的宽度,并确保地标名称在圆形图像下方可见。

10、在分隔符后添加MapView。地图显示在屏幕外,但可以向下滚动查看。

11、为后退按钮添加标题。将后退按钮的文本设置为“Landmarks”。

    var body: some View {
        @Bindable var modelData = modelData
        ScrollView {
            VStack {
                CircleImage(image: landmark.image.resizable())
                    .scaledToFit()
                
                Text(landmark.name)
                    .font(.headline)
                    .lineLimit(0)
                
                Toggle(isOn: $modelData.landmarks[landmarkIndex].isFavorite, label: {
                    Text("Favorite")
                })
                
                Divider()
                
                Text(landmark.park)
                    .font(.caption)
                    .bold()
                    .lineLimit(0)
                
                Text(landmark.state)
                    .font(.caption)
                
                Divider()
                
                MapView(coordinate: landmark.locationCoordinate)
                    .scaledToFit()
            }.padding(16)
        }.navigationTitle("Landmarks")
    }

添加地标列表

为iOS创建的LandmarkList也适用于手表应用,它会自动导航到刚刚为watchOS编译时创建的手表地标详情视图。接下来,将把列表连接到手表的ContentView,这样它就可以作为手表应用的顶层视图。

1、在 WatchLandmarks Watch App 文件夹中选择ContentView。

与LandmarkDetail一样,watchOS目标的内容视图与iOS目标的名称相同。保持名称和接口相同可以方便地在目标之间共享文件。

watchOS应用程序的根视图显示默认的 “Hello, World!” 消息。

2、修改ContentView,使其显示列表视图。

确保为预览提供模型数据作为环境。LandmarksApp(我这里是InterfacingWithUIKitApp)已经在运行时的应用级别提供了这个,就像它在iOS中所做的那样,但还必须为任何需要它的预览提供它。

struct ContentView: View {
    var body: some View {
        LandmarkList()
    }
}


#Preview {
    ContentView()
        .environment(ModelData())
}

3、确保在实时预览检查应用程序的行为。

创建自定义通知界面

watchOS平台的Landmarks应用已经接近完成了。在最后一节中,会创建一个通知界面,当用户的地理位置靠近自己收藏过的地标位置时会收到通知提示用户,通知界面展示当前正在接近的地标相关信息。

提示:本节只讲当用户收到通知时怎样显示通知界面,不涉及怎样设置和发送通知给用户的内容。

1、添加一个新的自定义视图到 WatchLandmarks Watch App 文件夹 NotificationView.swift,并创建一个视图来显示有关地标、标题和消息的信息。

struct NotificationView: View {
    var title: String?
    var message: String?
    var landmark: Landmark?


    var body: some View {
        VStack {
            if let landmark {
                CircleImage(image: landmark.image.resizable())
                    .scaledToFit()
            }


            Text(title ?? "Unknown Landmark")
                .font(.headline)


            Divider()


            Text(message ?? "You are within 5 miles of one of your favorite landmarks.")
                .font(.caption)
        }
    }
}

2、添加一个预览,用于设置通知视图的标题、消息和地标属性。

这将显示提供数据时通知视图的预览。因为任何通知值都可以为nil,所以在没有提供数据时保持通知视图的默认预览非常有用。

#Preview {
    NotificationView(title: "Turtle Rock", message: "You are within 5 miles of Turtle Rock.", landmark: ModelData().landmarks[0])
}

3、创建一个新的Swift文件NotificationController.swift,并添加一个包含landmark、title和message属性的托管控制器结构。

这些属性存储有关传入通知的值。

import WatchKit
import SwiftUI
import UserNotifications


class NotificationController: WKUserNotificationHostingController<NotificationView> {
    var landmark: Landmark?
    var title: String?
    var message: String?
    
    override var body: NotificationView {
        NotificationView()
    }
}

4、更新body()方法来使用这些属性。此方法实例化前面创建的通知视图。

    override var body: NotificationView {
        NotificationView(
            title: title,
            message: message,
            landmark: landmark
        )
    }

5、定义landmarkIndexKey。可以使用此键从通知中提取地标索引。

    let landmarkIndexKey = "landmarkIndex"

6、添加 didReceive(_:) 方法来解析来自通知的数据。

这个方法更新控制器的属性。调用此方法后,系统将使控制器的body属性失效,从而更新通知视图。然后,系统将通知显示在Apple Watch上。

    override func didReceive(_ notification: UNNotification) {
        let modelData = ModelData()


        let notificationData =
            notification.request.content.userInfo as? [String: Any]


        let aps = notificationData?["aps"] as? [String: Any]
        let alert = aps?["alert"] as? [String: Any]


        title = alert?["title"] as? String
        message = alert?["body"] as? String


        if let index = notificationData?[landmarkIndexKey] as? Int {
            landmark = modelData.landmarks[index]
        }
    }

当Apple Watch收到通知时,它会在你的应用程序中寻找与该通知类别相关的场景。

7、转到LandmarksApp(我这里是InterfacingWithUIKitApp)并使用LandmarkNear类别添加一个WKNotificationScene。

这个场景只对watchOS有意义,所以添加条件编译。

        #if os(watchOS)
        WKNotificationScene(controller: NotificationController.self, category: "LandmarkNear")
        #endif

在应用程序可以显示通知之前,需要请求权限。

8、转到ContentView并请求授权以启用通知中心的通知。

使用异步任务修改器发出请求,SwiftUI在内容视图首次出现时调用该修改器。

struct ContentView: View {
    var body: some View {
        LandmarkList()
            .task {
                let center = UNUserNotificationCenter.current()
                _ = try? await center.requestAuthorization(
                    options: [.alert, .sound, .badge]
                )
            }
    }
}

使用LandmarkNear类别配置测试数据(payload),并传递通知控制器期望的数据。

9、添加一个新的通知模拟文件到 WatchLandmarks Watch App 文件夹,名为 PushNotificationPayload.apns。

不要将 PushNotificationPayload 文件添加到任何目标,因为它不是应用的一部分。

10、更新title, body, category, landmarkIndex和Simulator Target Bundle属性。请确保将“类别”设置为“LandmarkNear”。还可以删除教程中不使用的任何键,例如副标题、WatchKit Simulator Actions和customKey。

{
    "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.apple-samplecode.Landmarks.watchkitapp"
}

注意:Simulator Target Bundle 一定要填写这个watchOS应用的 Bundle id。

Payload文件是用来模拟从服务端发送的远程推送的数据。

11、在模拟器上构建并运行WatchLandmarks Watch App方案。第一次运行这款应用时,系统会请求发送通知的许可。选择允许。

12、在授予权限后,使用Xcode停止应用程序,然后将 PushNotificationPayload 文件拖到表盘上。

模拟器显示一个可滚动的通知,其中包括:应用程序的图标以帮助识别地标应用程序作为发送者,通知视图和通知操作的按钮。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/770482.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【TS】TypeScript 中的 any 与 unknown:理解与实践

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 TypeScript 中的 any 与 unknown&#xff1a;理解与实践一、引言二、any&#x…

找不到msvcr110.dll是怎么回事?彻底解决msvcr110.dll丢失的方法

当您的电脑提示遇到msvcr110.dll丢失时&#xff0c;您知道如何解决此问题吗&#xff1f;事实上&#xff0c;解决此类dll文件丢失的问题相对较为简单。只要我们深入了解msvcr110.dll丢失的具体情况&#xff0c;便可轻松解决此问题。以下为您介绍msvcr110.dll修复方法。 一&#…

vue table表格 ( parseTime-格式化时间)

<el-table-column label"发布时间" width"420px" prop"bidPublishDatetime"><template slot-scope"scope"><span>{{ parseTime(scope.row.bidPublishDatetime, {y}-{m}-{d}) }}</span></template></…

从手工到智能:乐财业鹦鹉系统引领财税管理新纪元

随着税制改革的不断施行&#xff0c;我国数字经济顶层设计与地方推进举措相结合的政策体系已基本完善。中小企业的数字化转型尤为关键&#xff0c;也是大势所趋。 精益研发 数智创新 乐财业以敢于创新的精神&#xff0c;扎根在财税行业数字化的土壤&#xff0c;历时3年的精心研…

海豚调度监控:新增依赖缺失巡检,上游改动再也不用担心了!

&#x1f4a1; 本系列文章是 DolphinScheduler 由浅入深的教程&#xff0c;涵盖搭建、二开迭代、核心原理解读、运维和管理等一系列内容。适用于想对 DolphinScheduler了解或想要加深理解的读者。 祝开卷有益:) 用过 DolphinScheduler 的小伙伴应该都知道&#xff0c;Dolphin…

SpringBoot整合DataX数据同步(自动生成job文件)

SpringBoot整合Datax数据同步 文章目录 SpringBoot整合Datax数据同步1.简介设计理念 DataX3.0框架设计DataX3.0核心架构核心模块介绍DataX调度流程 2.DataX3.0插件体系3.数据同步1.编写job的json文件2.进入bin目录下&#xff0c;执行文件 4.SpringBoot整合DataX生成Job文件并执…

【Linux】目录和文件的权限意义

现在我们知道了Linux系统内文件的三种身份&#xff08;拥有者、用户组与其他人&#xff09;&#xff0c;知道每种身份都有三种权限&#xff08;rwx&#xff09;&#xff0c;也知道能够使用chown、chgrp、chmod修改这些权限与属性&#xff0c;当然&#xff0c;利用IS-l去查看文件…

一文了解“大数据招商思维”,读懂什么是大数据招商!

近年来&#xff0c;随着大数据及人工智能等新一代信息技术的快速发展&#xff0c;数据作为重要的资源和资产&#xff0c;成为推动经济发展的核心驱动力&#xff0c;广泛应用于各个领域&#xff0c;深刻的改变着我们的生产和生活方式。那么对于“招商引资”来说&#xff0c;大数…

超级加密狗——CBS(赛博锁)

智能终端设备安全现状&#xff1a; 随着网络和智能终端普及&#xff0c;云管端的智能物联应用越来越多&#xff0c;如何保证云端平台安全&#xff0c;以及各种智能终端&#xff08;含智能仪器&#xff0c;车载终端、智能摄像头、工控机、网关路由器、智能设备、 IoT设备等&…

3D模型格式转换工具HOOPS Exchange如何实现对PRC文档的支持?

随着三维模型在各个行业中的应用越来越广泛&#xff0c;高效、准确的3D模型格式转换工具变得尤为重要。在众多工具中&#xff0c;HOOPS Exchange因其强大的功能和广泛的格式支持赢得了用户的青睐。本文将详细探讨HOOPS Exchange如何实现对PRC&#xff08;Product Representatio…

XLSX + LuckySheet + LuckyExcel实现前端的excel预览

文章目录 功能简介简单代码实现效果参考 功能简介 通过LuckyExcel的transformExcelToLucky方法&#xff0c; 我们可以把一个文件直接转成LuckySheet需要的json字符串&#xff0c; 之后我们就可以用LuckySheet预览excelLuckyExcel只能解析xlsx格式的excel文件&#xff0c;因此对…

封装stater时配置导入配置类提示功能

提示功能如下 使用注解导入配置属性时添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency>

Element中的选择器组件Select (一级选择组件el-select)

简述&#xff1a;在 Element UI 中&#xff0c;ElSelect&#xff08;或简称为 Select&#xff09;是一个非常常用的选择器组件&#xff0c;它提供了丰富的功能来帮助用户从一组预定义的选项中选择一个或多个值。这里来简单记录一下 一. 组件和属性配置 <el-selectv-model&q…

为什么说牛企查查企业超好用?

步入职场的职场人士&#xff0c;经济相关专业的学生&#xff0c;都有查企业的需求&#xff0c;市面上查企业的软件平台那么多&#xff0c;每个功能都不怎么一样。 有的便宜&#xff0c;但是信息不全。有的信息还可以&#xff0c;但是会员费又很贵&#xff0c;让我这个打工人没…

垂直领域大模型的机遇与挑战:从构建到应用

在人工智能技术的浪潮中,大模型以其强大的数据处理和学习能力,成为推动科技进步的重要力量。然而,这种跨领域应用的过程并非一帆风顺,既面临挑战也蕴含机遇。本文从复旦大学的研究工作出发,详细分析大模型的机遇与挑战。 背景 GPT4技术报告指出,GPT4仍处于通用人工智…

kpatch制作内核热补丁步骤总结

零、原理及参考 kpatch入门实践教程-CSDN博客 Kpatch 使用过程及其原理-CSDN博客 一、准备工作 安装对应版本的kpatch-build.rpm并解决依赖diff -Naur dir1 dir2 > hot.patch 拿到补丁文件下载对应内核版本的src.rpm安装好对应的开发包kernel-debuginfo&#xff0c;kern…

SpringBoot 多数据源配置

目录 一. 引入maven依赖包 二. 配置yml 三、创建 xml 分组文件 四、切换数据源 一. 引入maven依赖包 <dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.6.1&…

既美观又方便的后台框架谁需要?进来就对了。

一套既美观又方便的后台框架可以大大幅节约开发时间和成本。 我们来一起看看几个明朗大气的管理控制台页面。 本文档会持续更新 模板编号&#xff1a;翠花_001模板编号&#xff1a;翠花_002模板编号&#xff1a;翠花_003

HTTP协议深入

1.了解web和网络基础 有客户端和服务端双方参与交互 客户端发送请求:request 服务端根据请求给出响应:response 请求通过URL来指定要获取都得资源 响应内容可以是HTML网页&#xff0c;或者用json表示的数据或者其他二进制文件内容 Web使用一种名为HTTP的协议作为规范&…

如何清理电脑内存?让电脑运行如飞!

电脑内存&#xff08;RAM&#xff09;的清理对于维持系统的流畅运行至关重要。随着使用时间的增加&#xff0c;系统内存会被各种应用程序和后台进程占用&#xff0c;导致系统响应变慢&#xff0c;甚至出现卡顿现象。通过有效地清理内存&#xff0c;可以提升电脑的性能&#xff…