SwiftUI 5.0(iOS 17)TipKit 让用户更懂你的 App

news2025/2/28 15:58:16

在这里插入图片描述

概览

作为我们秃头开发者来说,写出一款创意炸裂的 App 还不足以吸引用户眼球,更重要的是如何让用户用最短的时间掌握我们 App 的使用技巧。

在这里插入图片描述

从 iOS 17 开始, 推出了全新的 TipKit 框架专注于此事。有了它,我们再也不用自己写 App 用户帮助以及使用指南的逻辑和界面了。

使用 TipKit 非常简单,接下来就让我们一起走进 TipKit 的世界吧!

文章目录

  • 概览
  • 什么是 TipKit?
  • 创建一个 Tip
  • TipKit 显示的两种方式
  • TipKit 全局配置
  • TipKit 显示规则
  • 为 TipKit 增加更多互动性
  • 如何测试 TipKit?
  • 总结

本文代码全部在 Xcode 15 beta8 上编译,在 iOS 17 beta8 上运行。


什么是 TipKit?

在这里插入图片描述

TipKit 是  在 WWDC 23 上推出的一款新框架,用于在界面显示提示(Tips)来帮助用户快速发掘我们 App 的使用特性。

在这里插入图片描述
在这里插入图片描述

目前该框架仍属于 beta 阶段,意味着它还有很多不确定性。

如果我没有记错, 直到 Xcode beta4 才将 TipKit 提供给开发者,而且现在 官网 TipKit 的示例代码在 Xcode beta8 中已提示语法错误了(我们后面会说明):

在这里插入图片描述


对于  这种习惯性“谜之”行为的更多细节,感兴趣的小伙伴们可以到如下链接中观赏:

  • 有用的知识又增加了:为何无法编译某些  WWDC 官方视频中的代码?

创建一个 Tip

按照 SwiftUI 的“习性”,一个 Tip 同时意味着外观和逻辑双重含义。

创建一个提示很简单,只需遵循 Tip 协议即可:

struct FavoriteTip: Tip {
    var title: Text {
        Text("收藏最爱的图片")
            .bold()
    }
    
    var message: Text? {
        Text("将心仪的图片保存到相册中")
            .font(.headline)
            .foregroundStyle(.gray.gradient)
    }
}

Tip 协议还有很多其它可选属性,比如我们还可以为 Tip 界面进一步增加图片修饰:

struct FavoriteTip: Tip {
    var image: Image? {
        Image(systemName: "heart")
    }
}

TipKit 显示的两种方式

在 Tip 创建之后如何显示它们呢?有两种方式:嵌入和弹出。

我们可以直接将 Tip 嵌在视图中:

struct ContentView: View {
    let favTip = FavoriteTip()
    
    var body: some View {
        NavigationStack {
            VStack {
                
                TipView(favTip)
            }
            .padding()
            .navigationTitle("TitKit演示")
        }
    }
}

显示效果如下:

在这里插入图片描述

或者我们还可以将 Tip 直接依附于某一个视图,比如图片或按钮:

struct ContentView: View {
    let favTip = FavoriteTip()
    
    var body: some View {
        NavigationStack {
            VStack {...}
            .padding()
            .navigationTitle("TitKit演示")
            .toolbar {
                ToolbarItem {
                    Image(systemName: "heart")
                        .font(.title.weight(.black))
                        .foregroundStyle(.pink.gradient)
                        .popoverTip(favTip, arrowEdge: .top)
                }
            }
        }
    }
}

在这里插入图片描述

我们可以根据不同需求来组合使用这两种显示方式。

TipKit 全局配置

其实,TipKit 框架会在 App (本地目录)中存放一些相关的配置信息。理论上说,它们可能会通过 iCloud 同步到其它设备上去,这意味着在不同设备上相同 App 中的 TipKit 共享同一组配置。

我们可以进一步定制 TipKit 的配置细节,比如 Tip 显示频率、配置数据库保存的本地位置等等:

import SwiftUI
import TipKit

@main
struct TipKitTestApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .task {                    
                    try? Tips.configure([
                        .displayFrequency(.immediate),
                        .datastoreLocation(.applicationDefault)
                    ])
                    
                    // Xcode 15 beta4 中过时的语法,目前已不能使用:
                    /*
                    try? await Tips.configure {
                        DisplayFrequency(.immediate)
                        DatastoreLocation(.applicationDefault)
                    }*/
                }
        }
    }
}

如上代码所示,我们需要所有 Tip 立即显示,并且让系统决定配置数据存储的位置(我们也可以自己设置存储路径)。

在代码中,我们注释了之前官方示例中出错的代码片段,这些代码在 Xcode 15 beta8 中已不能使用。

TipKit 显示规则

除了全局 Tip 显示限制以外,我还可以设置单个 Tip 之间的显示规则。

比如,假设有两个提示,我们希望 FavoriteTip 在 StartTip 提示关闭后再显示,我们可以在 FavoriteTip 中用特定的规则(Rule)来表示这一约束:

struct FavoriteTip: Tip {
    // 其它代码从略
    
    var rules: [Rule] {
        #Rule(Self.$startTipHasDisplayed) { $0 == true}
    }
    
    @Parameter
    static var startTipHasDisplayed: Bool = false
    
}

现在,我们需要在 StartTip 提示关闭时将 FavoriteTip.startTipHasDisplayed 置为 true 才能触发 FavoriteTip 的显示:

struct ContentView: View {
    
    let startTip = StartTip()
    let favTip = FavoriteTip()
    
    var body: some View {
        NavigationStack {
            
            VStack {
                
                Image("1")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .onTapGesture {
                        // 关闭 startTip 提示
                        startTip.invalidate(reason: .actionPerformed)
                        // 触发 FavoriteTip 提升的显示
                        FavoriteTip.startTipHasDisplayed = true
                    }
                
                TipView(startTip)
            }
            .padding()
            .navigationTitle("TitKit演示")
            .toolbar {
                ToolbarItem {
                    Image(systemName: "heart")
                        .font(.title.weight(.black))
                        .foregroundStyle(.pink.gradient)
                        .popoverTip(favTip, arrowEdge: .top)
                }
            }
        }
    }
}

现在,只有等 StartTip 关闭后,FavoriteTip 提示才能显示出来:
在这里插入图片描述

为 TipKit 增加更多互动性

有时,我们希望提示为用户提供更丰富的交互功能,比如在 Tip 中提供按钮跳转到更详细的使用教程界面。

TipKit 为此也提供了很好的支持,我们可以为 Tip 添加 Action 来驱动交互行为:

struct FavoriteTip: Tip {
    // 其它代码从略
    
    var actions: [Action] {
        [
            Tip.Action(id: "learn-more", title: "了解更多"),
            Tip.Action(id: "forget", title: "下次再说")
        ]
    }
}

在 Tip Action 被触发时,我们可以执行自定义行为:

struct ContentView: View {
    
    let startTip = StartTip()
    let favTip = FavoriteTip()
    
    var body: some View {
        NavigationStack {
            
            VStack {
                
                Image("1")
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .onTapGesture {
                        startTip.invalidate(reason: .actionPerformed)
                        
                        FavoriteTip.startTipHasDisplayed = true
                    }
                
                TipView(startTip)
            }
            .padding()
            .navigationTitle("TitKit演示")
            .toolbar {
                ToolbarItem {
                    Image(systemName: "heart")
                        .font(.title.weight(.black))
                        .foregroundStyle(.pink.gradient)
                        .popoverTip(favTip, arrowEdge: .top){ action in
                            switch action.index {
                            case 0:
                                favTip.invalidate(reason: .tipClosed)

                                // 跳转到详细使用教程
                            case 1:
                                favTip.invalidate(reason: .tipClosed)
                                
                                // 直接退出提示
                            default:
                                break
                            }
                        }
                }
            }
        }
    }
}

现在,用户可以选择“了解更多”来进一步学习 App 的使用“秘技”了:

在这里插入图片描述

如何测试 TipKit?

TipKit 全局配置存储在本地带有持久化特性,为了便于开发者即时测试, 提供了一些方法来快速显示或隐藏全部或指定 Tip:

在这里插入图片描述

一般的,要想在 Xcode 预览中正确测试 TipKit 的行为,我们需要在每次视图刷新时重置 TipKit 数据库,否则 Tip 不会正常显示:

#Preview {
    ContentView()
        .task {
            // 在每次视图刷新时将 TipKit 数据库重置为初始状态
            try? Tips.resetDatastore()
            
            try? Tips.configure([
                .displayFrequency(.immediate),
                .datastoreLocation(.applicationDefault)
            ])
        }
}

总结

在本篇博文中,我们介绍了 SwiftUI 5.0(iOS 17)中新引进的开发框架 TipKit,使用它我们可以非常方便和快速的向用户介绍我们 App 中的各种特性和使用指南,小伙伴们还不快操练起来!

感谢观赏,再会!😎

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux系统编程-C++ I/O库

文章目录 一、 总述二、输出缓冲三、文件输入输出四、string流五、输入输出格式总述1、控制布尔值的格式2、指定整型值的进制3、在输出中指出进制4、控制浮点数格式4.1、 指定打印精度5、输出空白 六、未格式化的输入输出操作 一、 总述 C使用标准库类来处理面向流的输入和输出…

Linux之shell条件测试

目录 作用 基本用法 格式: 案例 -f 用法 [ ] 用法 [[]] 用法 (()) 语法 文件测试 参数 案例 编写脚本,测试文件是否存在,不存在则创建 整数测试 作用 操作符 案例 系统用户个数小于50的则输出信息 逻辑操作符 符号 案例 …

Spring----IOC、注解

目录 一、简介 二、spring的组成及拓展 spring七大模块 核心容器(Spring core) Spring上下文(Spring context) Spring面向切面编程(Spring AOP) Spring DAO模块 Spring ORM模块 Spring Web模块 Spring MVC框架(Spring WebMVC) 拓展 三、IOC理论 IOC本质 Hello S…

11.(Python数模)(预测模型三)多元线性回归预测

多元线性回归 简介 多元线性回归使用在自变量和因变量有逻辑相关性的情况中。在实际应用中,多元线性回归经常用于探索和解释变量之间的复杂关系,例如经济学、社会科学和自然科学等领域。它提供了一种统计工具来分析多个自变量对因变量的影响&#xff0…

Windows下使用source insight连接远程Linux机器写代码

命令总结 基本会用到的命令都在这里了,流程里面就不加命令了,自行看表格 流程 linux安装 samba,并确认版本,确认samba服务运行状态配置samba用户配置samba的配置文件 在文件最后增加 示例如下: security user [pub…

大模型参数高效微调PEFT的理解和应用

简介 近年的大型语言模型(也被称作基础模型),大多是采用大量资料数据和庞大模型参数训练的结果,比如常见的ChatGPT3有175B的模型参数量。随着Large Language Model(LLM)的横空出世,网络模型对常见问题的解答有了很强的…

分享大数据分析培训就业班课程内容

随着国家重视大数据,政府扶持大数据,大数据在企业中生根发芽根据人社部发布的《新职业--大数据工程技术人员就业景气现状分析报告》预计,未来5年,大数据行业的人才需求将保持30%-40%的增速,人才缺口总量将达到2000万人…

冠达管理股票分析:权益分派前买入好不好?

随着股票市场的不断升温,出资者们也越来越关注买入时机的把握。而其中一个重要的要素就是权益分配。那么,权益分配前买入好不好呢?本文将从多个视点进行剖析。 1、剖析权益分配对股价的影响,推断买入时机的合理性。权益分配是上市…

地图结构 | 图解占据栅格地图原理(附Matlab建图实验)

目录 0 专栏介绍1 栅格地图1.1 应用场景1.2 基本概念 2 占据栅格地图2.1 更新模型2.2 截断策略 3 仿真实现3.1 算法流程3.2 Matlab实现 0 专栏介绍 🔥附C/Python/Matlab全套代码🔥课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索…

蚂蚁开源编程大模型,提高开发效率

据悉,日前蚂蚁集团首次开源了代码大模型 CodeFuse,而这是蚂蚁自研的代码生成专属大模型,可以根据开发者的输入提供智能建议和实时支持,帮助开发者自动生成代码、自动增加注释、自动生成测试用例、修复和优化代码等kslouitusrtdf。…

小红书母婴行业文案怎么写,创作方向有哪些?

行业文案顾名思义就是有关于某个行业的文案,不过此类内容一般都具有商业性。随着互联网的深入,怎么对行业文案进行创作,也成为品牌的日常工作。今天为大家分享下小红书母婴行业文案怎么写,创作方向有哪些? 首先&#x…

arppy gis 读取text 并批量添加字段 arcpy.AddField_management

arppy gis 读取text 并批量添加字段 arcpy.AddField_management 例:给“省级行政区域”添加“A、B、C、D” 4个字段。 (1)用Excel制作出字段及其描述表,定义字段结构; (2)复制除标题行以为的内…

windows本地验证码识别小工具

windows本地验证码识别小工具 - 可以用在windows系统中,并可以集成在Java或python程序中 演示视频如下:可用于识别4-7位的字母数字组合的验证码(识别准确率在70% - 80%)。 验证码识别演示 本项目未开源,如需使用请联…

DELL 台式机的内置扬声器如何关闭

DELL 台式机的内置扬声器如何关闭? 点“开始”——控制面板——高清晰音频管理器——右上角“设备高级设置”——“播放设备”——点击“使前部和后部设备播放不同的音频流”前面的小方框——“确认”。ok了。

14-JVM调优实战-常量池详解

上一篇:13-JVM调优实战-3 最后,来一个算是补充拓展知识点,希望可以帮到你。 1.Class常量池与运行时常量池 Class常量池可以理解为是Class文件中的资源仓库。 Class文件中除了包含类的版本、字段、方法、接口等描述信息外,还有…

win7安装不了python3.10.8

今天安装python3.10.8,发现安装失败。原来是win7不支持python3.10.8。 如图: 安装出现问题: win7能安装python3哪个版本,我正在测试。到时补充编辑。

Web Components详解-Shadow DOM插槽

前言 插槽实际上也属于组件通信的一种方式,但是由于其强大的api和实用性,我将其单独拆开来介绍。 定义 Slot(插槽)是Web Components中一个重要的特性,它允许在组件内部定义占位符,以便父组件可以向其中插…

好用的工具推荐

1 chatgpt国内版 ChatMindAI ChatMindAI-智慧学习,办公无忧,AIGC让生活更简单https://x.chatmindai.net/explore

sovits远程访问设置

感谢阅读 把blocks.py的如下部分,false改为true

无涯教程-JavaScript - DOLLARDE函数

描述 DOLLARDE函数将以整数部分和小数部分(如1.02)表示的美元价格转换为以十进制数表示的美元价格。分数美元数字有时用于证券价格。值的小数部分除以您指定的整数。 语法 DOLLARDE (fractional_dollar, fraction)争论 Argument描述Required/OptionalFractional_dollarA nu…