日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

iOS录屏直播(四)主App和宿主App数据共享,通信功能实现

發(fā)布時(shí)間:2023/12/29 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS录屏直播(四)主App和宿主App数据共享,通信功能实现 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

    • CFNotificationCenterGetDarwinNotifyCenter
      • 發(fā)送通知
      • 接收通知
      • 注意事項(xiàng)
      • 遺留問(wèn)題
      • 補(bǔ)充

Morris_
2019.06.17

上一篇總結(jié)了一下AppGroup相關(guān)的基礎(chǔ)知識(shí),通過(guò)AppGroup組即可實(shí)現(xiàn)App之間共享同一塊存儲(chǔ)區(qū),以達(dá)到數(shù)據(jù)共享的目的。

在錄屏直播中,我們采用AppGroup這種方式可以實(shí)現(xiàn)宿主App和Extention的數(shù)據(jù)傳遞。在App中寫(xiě)入數(shù)據(jù),然后在Extention中讀取數(shù)據(jù),反之也可以。

這里主要總結(jié)一下跨進(jìn)程在兩個(gè)App中事件傳遞,從Extention發(fā)送通知到宿主App。

CFNotificationCenterGetDarwinNotifyCenter

平時(shí)開(kāi)發(fā)中發(fā)送通知我們使用NSNotificationCenter這個(gè)單例類(lèi),這個(gè)類(lèi)僅限在一個(gè)App內(nèi)部發(fā)送通知,如果跨進(jìn)程發(fā)通知的話就不能使用它了。

CFNotificationCenterGetDarwinNotifyCenter,是CoreFundation中的一個(gè)類(lèi),它可以實(shí)現(xiàn)跨進(jìn)程發(fā)送通知,將通知從Extention App發(fā)送到宿主App中。

如果我們的App要實(shí)現(xiàn)錄屏直播功能,需要添加Broadcast Upload Extension,這子App是負(fù)責(zé)采集、傳輸數(shù)據(jù)的,創(chuàng)建后會(huì)自動(dòng)生成一個(gè)類(lèi)SampleHandler。系統(tǒng)將采集到的錄屏數(shù)據(jù),通過(guò)SampleHandler中的Api輸出,同時(shí)有一些其他Api:

- (void)broadcastStartedWithSetupInfo:(NSDictionary<NSString *,NSObject *> *)setupInfo {[self sendNotificationForMessageWithIdentifier:@"broadcastStartedWithSetupInfo" userInfo:setupInfo]; }- (void)broadcastPaused {[self sendNotificationForMessageWithIdentifier:@"broadcastPaused" userInfo:nil]; }- (void)broadcastResumed {[self sendNotificationForMessageWithIdentifier:@"broadcastResumed" userInfo:nil]; }- (void)broadcastFinished {[self sendNotificationForMessageWithIdentifier:@"broadcastFinished" userInfo:nil]; }- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType {}

打開(kāi)手機(jī)桌面,然后長(zhǎng)按錄屏,選擇錄屏的App為我們自己的App,這時(shí)候就開(kāi)始錄制了。以上的接口就會(huì)被執(zhí)行。開(kāi)始錄屏執(zhí)行broadcastStartedWithSetupInfo,暫停錄制執(zhí)行broadcastPaused…

如果我們要將開(kāi)始、暫停、結(jié)束這些事件以消息的形式發(fā)送到宿主App中,需要使用CFNotificationCenterGetDarwinNotifyCenter。

發(fā)送通知

寫(xiě)一個(gè)發(fā)送通知的方法:

- (void)sendNotificationForMessageWithIdentifier:(nullable NSString *)identifier userInfo:(NSDictionary *)info {CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter();CFDictionaryRef userInfo = (__bridge CFDictionaryRef)info;BOOL const deliverImmediately = YES;CFStringRef identifierRef = (__bridge CFStringRef)identifier;CFNotificationCenterPostNotification(center, identifierRef, NULL, userInfo, deliverImmediately); }

這里的identifier是發(fā)送此條通知的標(biāo)識(shí),每個(gè)通知定義一個(gè)唯一的標(biāo)識(shí),以便接收端辨認(rèn)是哪一條通知。

接收通知

在Extension中發(fā)送通知后,在宿主App中接收消息。

需要接收通知,首先需要注冊(cè)該條通知,這里寫(xiě)了注冊(cè)和移除注冊(cè)通知的方法。這里的identifier需要和發(fā)送端保持一致。

- (void)registerForNotificationsWithIdentifier:(nullable NSString *)identifier {[self unregisterForNotificationsWithIdentifier:identifier];CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter();CFStringRef str = (__bridge CFStringRef)identifier;CFNotificationCenterAddObserver(center,(__bridge const void *)(self),MyHoleNotificationCallback,str,NULL,CFNotificationSuspensionBehaviorDeliverImmediately); } - (void)unregisterForNotificationsWithIdentifier:(nullable NSString *)identifier {CFNotificationCenterRef const center = CFNotificationCenterGetDarwinNotifyCenter();CFStringRef str = (__bridge CFStringRef)identifier;CFNotificationCenterRemoveObserver(center,(__bridge const void *)(self),str,NULL); }

這里我們需要接收多個(gè)通知消息,需要一一注冊(cè)才能收到消息:

注冊(cè)對(duì)應(yīng)事件的通知

- (void)addUploaderEventMonitor {NSLog(@"addUploaderEventMonitor");[self registerForNotificationsWithIdentifier:@"broadcastStartedWithSetupInfo"];[self registerForNotificationsWithIdentifier:@"broadcastPaused"];[self registerForNotificationsWithIdentifier:@"broadcastResumed"];[self registerForNotificationsWithIdentifier:@"broadcastFinished"];[self registerForNotificationsWithIdentifier:@"processSampleBuffer"];//這里同時(shí)注冊(cè)了紛發(fā)消息的通知,在宿主App中使用[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(broadcastInfo:) name:ScreenHoleNotificationName object:nil]; }

移除注冊(cè)的通知

- (void)removeUploaderEventMonitor {NSLog(@"removeUploaderEventMonitor");[self unregisterForNotificationsWithIdentifier:@"broadcastStartedWithSetupInfo"];[self unregisterForNotificationsWithIdentifier:@"broadcastPaused"];[self unregisterForNotificationsWithIdentifier:@"broadcastResumed"];[self unregisterForNotificationsWithIdentifier:@"broadcastFinished"];[self unregisterForNotificationsWithIdentifier:@"processSampleBuffer"];[[NSNotificationCenter defaultCenter] removeObserver:self name:ScreenHoleNotificationName object:nil]; }

MyHoleNotificationCallback是一個(gè)回調(diào)block,當(dāng)收到通知時(shí),就會(huì)回調(diào)這個(gè)block。它的實(shí)現(xiàn)如下:

static NSString * const ScreenHoleNotificationName = @"ScreenHoleNotificationName";void MyHoleNotificationCallback(CFNotificationCenterRef center,void * observer,CFStringRef name,void const * object,CFDictionaryRef userInfo) {NSString *identifier = (__bridge NSString *)name;NSObject *sender = (__bridge NSObject *)observer;//NSDictionary *info = (__bridge NSDictionary *)userInfo;NSDictionary *info = CFBridgingRelease(userInfo);NSLog(@"userInfo %@ %@",userInfo,info);NSDictionary *notiUserInfo = @{@"identifier":identifier};[[NSNotificationCenter defaultCenter] postNotificationName:ScreenHoleNotificationNameobject:senderuserInfo:notiUserInfo]; }

這里收到通知后,做了一步轉(zhuǎn)發(fā),將消息轉(zhuǎn)發(fā)出去,在在宿主App中發(fā)送通知。

在宿主App中收到MyHoleNotificationCallback這個(gè)回調(diào)后,我們將此條通知通過(guò)NSNotificationCenter紛發(fā)出去,App中其他地方如果需要監(jiān)聽(tīng)這些事件就可以注冊(cè)ScreenHoleNotificationName接收消息了。

如果其他地方不需要接收通知消息,則收到MyHoleNotificationCallback后直接處理就行,也不必再轉(zhuǎn)發(fā)了。

這樣事件傳遞,實(shí)現(xiàn)了宿主App和主App之間的事件通信。

- (void)broadcastInfo:(NSNotification *)noti {NSDictionary *userInfo = noti.userInfo;NSString *identifier = userInfo[@"identifier"];if ([identifier isEqualToString:@"broadcastStartedWithSetupInfo"]) {}if ([identifier isEqualToString:@"broadcastPaused"]) {}if ([identifier isEqualToString:@"broadcastResumed"]) {}if ([identifier isEqualToString:@"broadcastFinished"]) {}if ([identifier isEqualToString:@"processSampleBuffer"]) {} }

這塊只是在錄屏直播中是否有用,得根據(jù)具體的業(yè)務(wù)需求來(lái)看,有時(shí)候不需要將事件傳遞給宿主App,也就不用發(fā)送通知了。

注意事項(xiàng)

不要在- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType這個(gè)方法里發(fā)通知,這幾方法是采集到數(shù)據(jù)就會(huì)回調(diào),錄屏過(guò)程中一直被執(zhí)行,如果一直發(fā)送通知的話,會(huì)造成主線程卡頓,因?yàn)橥ㄖ峭竭M(jìn)行的。

遺留問(wèn)題

在發(fā)送通知的時(shí)候,可以傳遞一個(gè)參數(shù)userInfo,即CFNotificationCenterPostNotification(center, identifierRef, NULL, userInfo, deliverImmediately);

這個(gè)userInfo的傳值問(wèn)題我沒(méi)有解決,應(yīng)該是可以轉(zhuǎn)值的,可能是轉(zhuǎn)化問(wèn)題,不知道怎么弄,有知道的可以一起探討一下,或者直接在品論了告知,謝謝先。

補(bǔ)充

這里是之后補(bǔ)充的內(nèi)容

以下是別人的處理思路,出處

App 與 Extension 的代碼共用iOS 10 新增了很多種 Extension,包括本文提到的兩種 Broadcast Extension。主 App 與 Extension 屬于不同的兩個(gè)進(jìn)程,代碼邏輯也是分離的,而實(shí)際情況中,主 App 與 Extension 往往會(huì)包含相同的邏輯,需要共用代碼。

主 App 與 Extension 屬于兩個(gè)不同的 target,共用代碼,有以下幾種方式:

一份代碼創(chuàng)建兩個(gè)副本,分別加到 App 和 Extension 兩個(gè) target 中。這種方法簡(jiǎn)單粗暴而有效,只是,如果需要改動(dòng)邏輯,則需要改兩份代碼,想象一下,假如這種改動(dòng)很頻繁,世界上又有幾個(gè)程序員能受得了?

抽離公共代碼,放到獨(dú)立的 framework,然后兩個(gè) target 都依賴(lài)該 framework,這是標(biāo)準(zhǔn)而方便的做法。
使用 CocoaPods,只需要在 Podfile 中分別寫(xiě)兩個(gè) target 所依賴(lài)的 pod 即可,最簡(jiǎn)潔。

我覺(jué)得 使用 CocoaPods,只需要在 Podfile 中分別寫(xiě)兩個(gè) target 所依賴(lài)的 pod 即可,最簡(jiǎn)潔。 這個(gè)也是一個(gè)可考慮的思路。

總結(jié)

以上是生活随笔為你收集整理的iOS录屏直播(四)主App和宿主App数据共享,通信功能实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。