iOS16 基于ObjectiveC的實(shí)時(shí)活動(dòng)以及靈動(dòng)島

iOS16.1系統(tǒng)開始正式支持實(shí)時(shí)活動(dòng),更新Xcode為最新的14.1版本,(跟著官方文檔步驟)開始著手開發(fā)
官方文檔https://developer.apple.com/documentation/activitykit/displaying-live-data-with-live-activities
前情提要:項(xiàng)目是OC項(xiàng)目,且這次實(shí)時(shí)活動(dòng)沒有用到遠(yuǎn)程推送

1.新建OC項(xiàng)目,Info-Plist文件加入Bool類型的權(quán)限key值為:Supports Live Activities value為:YES
2.如果項(xiàng)目之前有過小組件,則不需要再創(chuàng)建新的Widget-Extension,直接在@main WidgetBundle里面添加要?jiǎng)?chuàng)建的Live-Activity組件即可(我們?cè)诤竺嫣砑樱?/h5>
3.(我是OC項(xiàng)目)在主項(xiàng)目里面新建一個(gè)Attributes.swift項(xiàng)目
Attributes

官方文檔有詳細(xì)講解,以我的為例

import Foundation
import ActivityKit

//我自己的Widget類
struct ZKWidgetAttributes: ActivityAttributes {
    public typealias ZKWidgetState = ContentState
    //可變參數(shù)(動(dòng)態(tài)參數(shù))
    public struct ContentState: Codable, Hashable {
        //參數(shù),當(dāng)前的監(jiān)測(cè)時(shí)間
        var monitorTime: ClosedRange<Date>
        var sleepProgress :Float 
    }
    var sleepGoal: Double
}

//定義一個(gè)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
    }
    
    //開啟一個(gè)實(shí)時(shí)活動(dòng)
    @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)")
        }
        
    }
    //更新一個(gè)實(shí)時(shí)活動(dòng)
    @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)
            }
        }
    }
   
  //結(jié)束一個(gè)實(shí)時(shí)活動(dòng)
    @objc public func stopActivity (){
        
        Task {
            for activity in Activity<ZKWidgetAttributes>.activities{
                await activity.end(dismissalPolicy: .immediate)
            }
        }
        self.cancelTimer()
    }
  //是否支持實(shí)施活動(dòng)(開關(guān)是否打開)
    @objc public func isOpenLiveActivity ()-> Bool {
        if !ActivityAuthorizationInfo().areActivitiesEnabled {
            return false
        }
        return true
    }
    //獲取實(shí)施活動(dòng)列表
    @objc public func getLiveActivityList () async{
        for await activity in Activity<ZKWidgetAttributes>.activityUpdates {
            print("Pizza delivery details: \(activity.attributes)")
        }
    }
    
    //開啟定時(shí)器
    @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("開始計(jì)時(shí):\(self.sleepTime)")
        print("目前進(jìn)度:\(self.progress)")
    }
    deinit {
        cancelTimer()
    }
    func cancelTimer() {
        timer?.invalidate()
        timer = nil
    }
}

tips 需要在Widget里用到我們?cè)谥鞴こ痰腁ttributes,需要在Attributes.swift文件右邊的Target Membership里面,勾上WidgetExtension,以確保組件也可以用到該文件

4.創(chuàng)建Widget

里面包括鎖屏界面的Widget以及靈動(dòng)島的Widget,這塊就自己用SWiftUI進(jìn)行布局即可
//當(dāng)然我們也可以通過不同的Attributes開啟不同的實(shí)時(shí)活動(dòng),傳入不同參數(shù),刻畫不同的Widget樣式

5.上截圖
鎖屏界面實(shí)時(shí)活動(dòng)
靈動(dòng)島實(shí)時(shí)活動(dòng)
放到最后

1.自己心中有個(gè)疑慮,如果實(shí)時(shí)活動(dòng)鎖屏組件上有個(gè)類似于圓環(huán)進(jìn)度條,如何做到實(shí)時(shí)刷新(沒有remote-push)),本人想法是,主項(xiàng)目有個(gè)計(jì)時(shí)器,然后調(diào)用updateActivity方法,但是可能會(huì)導(dǎo)致大量耗電,不是一個(gè)好的方法。
Text有一個(gè)(timerInterval: ClosedRange<Date>, pauseTime: Date? = nil, countsDown: Bool = true, showsHours: Bool = true)方法,可以動(dòng)畫的進(jìn)行倒計(jì)時(shí),也就是Apple官方給的披薩外賣demo。

就先到這,后期有啥再更新!
Github地址https://github.com/Superman-Frank/liveActivity

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容