在iOS应用中使用实时活动与灵动岛

简介: iOS16系统引入了实时活动与灵动岛相关的API。实时活动API能够让用户在桌面直接浏览到应用程序所提供的实时性较高的信息,例如比赛的比分信息,外卖的配送进度信息,票务信息等。在支持灵动岛的设备上,实时活动配合灵动岛,更是能带给用户沉浸式的信息获取体验,在某些特定应用场景下非常有用。

在iOS应用中使用实时活动与灵动岛

iOS16系统引入了实时活动与灵动岛相关的API。实时活动API能够让用户在桌面直接浏览到应用程序所提供的实时性较高的信息,例如比赛的比分信息,外卖的配送进度信息,票务信息等。在支持灵动岛的设备上,实时活动配合灵动岛,更是能带给用户沉浸式的信息获取体验,在某些特定应用场景下非常有用。

1 - 引言

从iOS16开始,实时活动能够在锁屏、待机桌面以及灵动岛等位置提供信息更新展示。在某些特定场景下,实时活动可以提供给用户几个小时内掌握实时事件、活动或任务更新。常见的应用场景有:

- 外卖类应用实时提供用户配送进度,剩余时间。

- 赛事类应用的实时分数。

- 健身类应用与可穿戴设备的实时体能状态更新。

实时应用将会展示在设备的:

- 锁屏页面

- 通知列表顶部

- 在支持灵动岛的设备上,在灵动岛位置展示

- 不支持灵动岛的设备上,实时活动的更新会在屏幕顶部弹出通知

- 待机显示时,实时活动会充满整个屏幕

需要注意,灵动岛的可可显示区域优先,在开发实时活动时,在设计上可以参考下面的最佳实践文档:

https://developer.apple.com/cn/design/human-interface-guidelines/live-activities/

2 - 开发实时活动与适配灵动岛

首先,要支持实时活动需要在工程中创建一个Widget Extension,实时活动本身也是小组件的一种。如下图所示:

截屏2023-12-30 20.13.49.png

需要注意,在创建Widget小组件时,将Include Live Activicy选中,如下图:

截屏2023-12-30 20.16.22.png

虽然实时活动也是小组件,但其他普通的Widget区别很大,小组件是通过Timeline来进行更新,而实时活动只能通过App触发更新或特殊Push更新和关闭;小组件需要用户手动添加使用,而实时活动则是由主App进行开启。创建好Tatget后,模版自带3个文件,其中LiveWidgetLiveActivity中实时活动的核心框架代码,我们做些简单的修改,如下:

import ActivityKit
import WidgetKit
import SwiftUI
// 状态结构体
struct LiveWidgetAttributes: ActivityAttributes {
   
   
    public struct ContentState: Codable, Hashable {
   
   
        // 动态的状态,有App或Push来触发更新
        var score: String
    }

    // 静态的状态,实时活动开启时指定
    var name: String
    var teamA: String
    var teamB: String
}

// 编写SwiftUI页面
struct LiveWidgetLiveActivity: Widget {
   
   
    var body: some WidgetConfiguration {
   
   
        ActivityConfiguration(for: LiveWidgetAttributes.self) {
   
    context in
            // Lock screen/banner UI goes here
            VStack {
   
   
                Text(context.attributes.name)
                Text("💻💻💻💻💻💻💻💻💻💻💻")
                Text("\(context.attributes.teamA) 对战 \(context.attributes.teamB)")
                Text("当前比分:\(context.state.score)")
            }.padding(.all, 10)
            .activityBackgroundTint(Color.cyan)
            .activitySystemActionForegroundColor(Color.black)

        } dynamicIsland: {
   
    context in
            DynamicIsland {
   
   
                // Expanded UI goes here.  Compose the expanded UI through
                // various regions, like leading/trailing/center/bottom
                DynamicIslandExpandedRegion(.leading) {
   
   
                    Text(context.attributes.teamA)
                }
                DynamicIslandExpandedRegion(.trailing) {
   
   
                    Text(context.attributes.teamB)
                }
                DynamicIslandExpandedRegion(.center) {
   
   
                    Text("\(context.attributes.name)")
                }
                DynamicIslandExpandedRegion(.bottom) {
   
   
                    Text("当前比分:\(context.state.score)")
                }
            } compactLeading: {
   
   
                Text(context.attributes.teamA)
            } compactTrailing: {
   
   
                Text(context.attributes.teamB)
            } minimal: {
   
   
                Text("🆚")
            }
            .widgetURL(URL(string: "http://www.apple.com"))
            .keylineTint(Color.red)
        }
    }
}

上面代码中,LiveWidgetAttributes定义实时活动所需要的数据模型,其中直接定义的属性可以理解为静态的属性,即当实时活动开启时就确定的数据,例如比赛参与的队伍,外卖的订单信息等。其中的ContentState用来定义需要更新的数据,例如比分数据,外卖剩余时间数据等。

实时活动只能使用SwiftUI来编写,如上代码所示ActivityConfiguration配置实时活动组件,dynamicIsland参数用来对灵动岛进行适配。

在进行灵动岛的适配时,需要对灵动岛的各种状态进行配置:

1 - 展开状态下的灵动岛。

2 - 长条状态下的灵动岛。

3 - mini状态下的灵动岛。

展开状态下的灵动岛分为左右中下4部分,如上代码所示可以对每个部分进行布局,在开启实时活动时,长按灵动岛可以进入展开状态,效果如下图所示:

Simulator Screenshot - iPhone 15 Pro - 2023-12-30 at 20.38.23.png

长条状态是灵动岛的默认状态,可以对左右两部分进行配置,效果如下图:

Simulator Screenshot - iPhone 15 Pro - 2023-12-30 at 20.40.41.png

当同时有多个App开启了实时活动时,灵动岛上将只展示一个圆圈,此时即是mini状态,通常可以配置为一个图标,如下图所示:

Simulator Screenshot - iPhone 15 Pro - 2023-12-30 at 20.42.46.png

在锁屏或拉下通知栏时,实时活动将展示在所有通知的最上方,如下图所示:

Simulator Screenshot - iPhone 15 Pro - 2023-12-30 at 20.44.07.png

在iOS17中,当设备在横屏充电时,会自动进入待机状态,如果有实时活动,实时活动将占据整个待机页面,如下图:

Simulator Screenshot - iPhone 15 Pro - 2023-12-30 at 20.45.55.png

3 - 实时活动的开启与更新

前面有提到过,实时活动只能通过主App来开启,LiveWidgetLiveActivity结构体需要在主App中被引入。首先设置LiveWidgetLiveActivity的Target Membership为主App与小组件Target共享,如下图:

截屏2023-12-30 20.50.52.png

在主App中调用如下代码来进行实时活动的开启:

import UIKit
// 框架引入
import ActivityKit
class ViewController: UIViewController {
   
   
    override func viewDidLoad() {
   
   
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        let attri = LiveWidgetAttributes(name: "XX杯英雄电竞总决赛", teamA: "王族队", teamB: "斩星队")
        let state = LiveWidgetAttributes.ContentState(score: "2-1")
        do {
   
   
            try Activity.request(attributes: attri, contentState: state, pushType: .token) }
        catch {
   
   
            print(error)
        }

    }
}

Activicy.request方法来请求开启一个实时活动,Activicy中还有一些方法用来对实时活动进行更新和获取更新实时活动的PushToken,下面是其中封装的核心属性方法的详细解释:

public class Activity<Attributes> : Identifiable where Attributes : ActivityAttributes {
   
   
    // 开启一个实时活动,其中PushType目前只支持Token模型的Push更新
    public static func request(attributes: Attributes, content: ActivityContent<Activity<Attributes>.ContentState>, pushType: PushType? = nil) throws -> Activity<Attributes>
    // 获取应用当前的实时活动
    public static var activities: [Activity<Attributes>] {
   
    get }
    // 异步队列,用来监听实时活动的更新
    public static var activityUpdates: Activity<Attributes>.ActivityUpdates {
   
    get }
    // 当前实时活动的状态: 活跃,已结束,已移除
    public var activityState: ActivityState {
   
    get }
    // 用来监听状态变更
    public var activityStateUpdates: Activity<Attributes>.ActivityStateUpdates {
   
    get }
    // 通过Push更新实时活动时的PushToken
    public var pushToken: Data? {
   
    get }
    // 异步的对实时活动状态进行更新
    public func update(using contentState: Activity<Attributes>.ContentState) async
    public func update(_ content: ActivityContent<Activity<Attributes>.ContentState>) async
    public func update(using contentState: Activity<Attributes>.ContentState, alertConfiguration: AlertConfiguration? = nil) async
    public func update(_ content: ActivityContent<Activity<Attributes>.ContentState>, alertConfiguration: AlertConfiguration? = nil) async
    // 结束一个实时活动
    public func end(using contentState: Activity<Attributes>.ContentState? = nil, dismissalPolicy: ActivityUIDismissalPolicy = .default) async
    public func end(_ content: ActivityContent<Activity<Attributes>.ContentState>?, dismissalPolicy: ActivityUIDismissalPolicy = .default) async
}

最后,需要注意,此处进行更新实时活动的Push必须是基于Token验证的APNs,不能是基于证书验证的APNs,此处的Token不是从Application接口拿到的Device Token,而是从Apple Developer后台创建的鉴权Token,另外,基于Token的Push认证要比基于证书的更加方便,且无需关心过期时间,如果你的应用的APNs目前依然是基于证书的,则需要进行改造后才能使用其来更新实时活动。

目录
相关文章
|
1月前
|
设计模式 安全 Swift
探索iOS开发:打造你的第一个天气应用
【9月更文挑战第36天】在这篇文章中,我们将一起踏上iOS开发的旅程,从零开始构建一个简单的天气应用。文章将通过通俗易懂的语言,引导你理解iOS开发的基本概念,掌握Swift语言的核心语法,并逐步实现一个具有实际功能的天气应用。我们将遵循“学中做,做中学”的原则,让理论知识和实践操作紧密结合,确保学习过程既高效又有趣。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你打开一扇通往iOS开发世界的大门。
|
1月前
|
搜索推荐 IDE API
打造个性化天气应用:iOS开发之旅
【9月更文挑战第35天】在这篇文章中,我们将一起踏上iOS开发的旅程,通过创建一个个性化的天气应用来探索Swift编程语言的魅力和iOS平台的强大功能。无论你是编程新手还是希望扩展你的技能集,这个项目都将为你提供实战经验,帮助你理解从构思到实现一个应用的全过程。让我们开始吧,构建你自己的天气应用,探索更多可能!
63 1
|
3月前
|
搜索推荐 API 开发工具
打造个性化天气应用:从零开始的iOS开发之旅
【8月更文挑战第31天】本文是一篇针对初学者的iOS应用开发指南,将引导读者通过Swift和iOS SDK构建一个简单而美观的天气应用。我们将探索如何利用API获取实时天气数据,并在应用中实现用户友好的界面设计。文章不仅包括代码示例,还提供了设计理念和用户体验优化的建议,旨在帮助初学者理解iOS开发的基础知识,并激发他们创造个性化应用的兴趣。
|
3月前
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
9天前
|
JSON 前端开发 API
探索iOS开发之旅:打造你的第一个天气应用
【10月更文挑战第36天】在这篇文章中,我们将踏上一段激动人心的旅程,一起构建属于我们自己的iOS天气应用。通过这个实战项目,你将学习到如何从零开始搭建一个iOS应用,掌握基本的用户界面设计、网络请求处理以及数据解析等核心技能。无论你是编程新手还是希望扩展你的iOS开发技能,这个项目都将为你提供宝贵的实践经验。准备好了吗?让我们开始吧!
|
18天前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户点击按钮时,按钮将从圆形变为椭圆形,颜色从蓝色渐变到绿色;释放按钮时,动画以相反方式恢复。通过UIView的动画方法和弹簧动画效果,实现平滑自然的过渡。
33 1
|
27天前
|
Swift iOS开发 UED
如何使用Swift和UIKit在iOS应用中实现自定义按钮动画
【10月更文挑战第18天】本文通过一个具体案例,介绍如何使用Swift和UIKit在iOS应用中实现自定义按钮动画。当用户按下按钮时,按钮将从圆形变为椭圆形并从蓝色渐变为绿色;释放按钮时,动画恢复原状。通过UIView的动画方法和弹簧动画效果,实现平滑自然的动画过渡。
47 5
|
2月前
|
存储 IDE 开发工具
移动应用开发之旅:打造你的首个iOS应用
【9月更文挑战第23天】在数字化浪潮中,移动应用已成为连接用户与数字世界的关键桥梁。本文将带领读者踏上开发属于自己的第一个iOS移动应用的旅程,从理解移动操作系统的核心概念出发,逐步深入到实际的应用构建过程中。通过简洁明了的语言和具体的代码示例,我们将一起探索如何在苹果的iOS平台上实现一个简单的“待办事项列表”应用,让读者不仅能够学习到编程知识,还能体会到将想法转化为现实产品的成就感。无论你是编程新手还是希望扩展技能的开发者,这篇文章都将为你提供一个实用的指南,帮助你迈出成为移动应用开发者的第一步。
|
2月前
|
开发框架 Android开发 iOS开发
探索安卓与iOS开发的差异:构建未来应用的指南
在移动应用开发的广阔天地中,安卓与iOS两大平台各占半壁江山。本文将深入浅出地对比这两大操作系统的开发环境、工具和用户体验设计,揭示它们在编程语言、开发工具以及市场定位上的根本差异。我们将从开发者的视角出发,逐步剖析如何根据项目需求和目标受众选择适合的平台,同时探讨跨平台开发框架的利与弊,为那些立志于打造下一个热门应用的开发者提供一份实用的指南。
61 5
|
2月前
|
Swift iOS开发 UED
揭秘一款iOS应用中令人惊叹的自定义动画效果,带你领略编程艺术的魅力所在!
【9月更文挑战第5天】本文通过具体案例介绍如何在iOS应用中使用Swift与UIKit实现自定义按钮动画,当用户点击按钮时,按钮将从圆形变为椭圆形并从蓝色渐变到绿色,释放后恢复原状。文中详细展示了代码实现过程及动画平滑过渡的技巧,帮助读者提升应用的视觉体验与特色。
62 11