iOS16.1系统开始正式支持实时活动,更新Xcode为最新的14.1版本,(跟着官方文档步骤)开始着手开发
官方文档https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities
前情提要:项目是OC项目,且这次实时活动没有用到远程推送
1.新建OC项目,Info-Plist文件加入Bool类型的权限key值为:Supports Live Activities
value为:YES
2.如果项目之前有过小组件,则不需要再创建新的Widget-Extension,直接在@main WidgetBundle
里面添加要创建的Live-Activity
组件即可(我们在后面添加)
3.(我是OC项目)在主项目里面新建一个Attributes.swift项目
Attributes
官方文档有详细讲解,以我的为例
import Foundation
import ActivityKit
//我自己的Widget类
struct ZKWidgetAttributes: ActivityAttributes {
public typealias ZKWidgetState = ContentState
//可变参数(动态参数)
public struct ContentState: Codable, Hashable {
//参数,当前的监测时间
var monitorTime: ClosedRange<Date>
var sleepProgress :Float
}
var sleepGoal: Double
}
//定义一个Manager类(单例)
@available(iOS 16.1, *)
public class ZkActivityManager : NSObject{
var timer: Timer?
var sleepTime: Int = 0
var progress: Float = 0.0
static let defaultManager: ZkActivityManager = ZkActivityManager()
@objc public class func defaultManage() -> ZkActivityManager
{
return ZkActivityManager.defaultManager
}
//开启一个实时活动
@objc public func startActivity(sleepGoal:Int){
self.startTimer()
let attributes = ZKWidgetAttributes(sleepGoal: Double(sleepGoal))
let initialConetntState = ZKWidgetAttributes.ZKWidgetState(monitorTime: Date()...Date().addingTimeInterval(12 * 60 * 60 ),sleepProgress: Float(self.progress))
do {
let activity = try Activity<ZKWidgetAttributes>.request(attributes: attributes, contentState: initialConetntState, pushType: nil)
print("Requested a pizza delivery Live Activity \(activity.id)")
} catch (let error) {
print("Error requesting pizza delivery Live Activity \(error.localizedDescription)")
}
}
//更新一个实时活动
@objc public func updateActivity (){
Task {
let updateStatus = ZKWidgetAttributes.ZKWidgetState(monitorTime: Date()...Date().addingTimeInterval(0.2 * 60),sleepProgress:Float(self.progress))
for activity in Activity<ZKWidgetAttributes>.activities{
await activity.update(using: updateStatus)
}
}
}
//结束一个实时活动
@objc public func stopActivity (){
Task {
for activity in Activity<ZKWidgetAttributes>.activities{
await activity.end(dismissalPolicy: .immediate)
}
}
self.cancelTimer()
}
//是否支持实施活动(开关是否打开)
@objc public func isOpenLiveActivity ()-> Bool {
if !ActivityAuthorizationInfo().areActivitiesEnabled {
return false
}
return true
}
//获取实施活动列表
@objc public func getLiveActivityList () async{
for await activity in Activity<ZKWidgetAttributes>.activityUpdates {
print("Pizza delivery details: \(activity.attributes)")
}
}
//开启定时器
@objc public func startTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(recordTime), userInfo: nil, repeats: true)
if let curTimer : Timer = timer {
RunLoop.main.add(curTimer, forMode: .common)
}
}
@objc func recordTime(){
sleepTime += 1
self.progress = Float(sleepTime) / 480.0 / 60
print("开始计时:\(self.sleepTime)")
print("目前进度:\(self.progress)")
}
deinit {
cancelTimer()
}
func cancelTimer() {
timer?.invalidate()
timer = nil
}
}
tips
需要在Widget里用到我们在主工程的Attributes,需要在Attributes.swift文件右边的Target Membership
里面,勾上WidgetExtension,以确保组件也可以用到该文件
4.创建Widget
里面包括锁屏界面的Widget以及灵动岛的Widget,这块就自己用SWiftUI进行布局即可
//当然我们也可以通过不同的Attributes开启不同的实时活动,传入不同参数,刻画不同的Widget样式
5.上截图
锁屏界面实时活动 灵动岛实时活动放到最后
1.自己心中有个疑虑,如果实时活动锁屏组件上有个类似于圆环进度条,如何做到实时刷新(没有remote-push)),本人想法是,主项目有个计时器,然后调用updateActivity
方法,但是可能会导致大量耗电,不是一个好的方法。
Text有一个(timerInterval: ClosedRange<Date>, pauseTime: Date? = nil, countsDown: Bool = true, showsHours: Bool = true)
方法,可以动画的进行倒计时,也就是Apple官方给的披萨外卖demo。
就先到这,后期有啥再更新!
Github地址https://github.com/Superman-Frank/liveActivity
网友评论