美文网首页iOS各问题归类
iOS16 基于ObjectiveC的实时活动以及灵动岛

iOS16 基于ObjectiveC的实时活动以及灵动岛

作者: 我是卖报的小行家 | 来源:发表于2022-11-07 12:07 被阅读0次

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

相关文章

网友评论

    本文标题:iOS16 基于ObjectiveC的实时活动以及灵动岛

    本文链接:https://www.haomeiwen.com/subject/kxewtdtx.html