資料介紹
軟件簡介
coobjc 為 Objective-C 和 Swift 提供了協(xié)程功能。coobjc 支持 await、generator 和 actor model,接口參考了 C# 、Javascript 和 Kotlin 中的很多設(shè)計。我們還提供了?cokit 庫為 Foundation 和 UIKit 中的部分 API 提供了協(xié)程化支持,包括 NSFileManager、JSON、NSData 與 UIImage 等。coobjc 也提供了元組的支持。
0x0 iOS 異步編程問題
基于 Block 的異步編程回調(diào)是目前 iOS 使用最廣泛的異步編程方式,iOS 系統(tǒng)提供的 GCD 庫讓異步開發(fā)變得很簡單方便,但是基于這種編程方式的缺點也有很多,主要有以下幾點:
- 容易進(jìn)入"嵌套地獄"
- 錯誤處理復(fù)雜和冗長
- 容易忘記調(diào)用 completion handler
- 條件執(zhí)行變得很困難
- 從互相獨立的調(diào)用中組合返回結(jié)果變得極其困難
- 在錯誤的線程中繼續(xù)執(zhí)行
- 難以定位原因的多線程崩潰
- 鎖和信號量濫用帶來的卡頓、卡死
上述問題反應(yīng)到線上應(yīng)用本身就會出現(xiàn)大量的多線程崩潰。
0x1 解決方案
上述問題在很多系統(tǒng)和語言中都會遇到,解決問題的標(biāo)準(zhǔn)方式就是使用協(xié)程。這里不介紹太多的理論,簡單說協(xié)程就是對基礎(chǔ)函數(shù)的擴展,可以讓函數(shù)異步執(zhí)行的時候掛起然后返回值。協(xié)程可以用來實現(xiàn) generator ,異步模型以及其他強大的能力。
Kotlin 是這兩年由 JetBrains 推出的支持現(xiàn)代多平臺應(yīng)用的靜態(tài)編程語言,支持 JVM ,Javascript ,目前也可以在 iOS 上執(zhí)行,這兩年在開發(fā)者社區(qū)中也是比較火。
在 Kotlin 語言中基于協(xié)程的 async/await ,generator/yield 等異步化技術(shù)都已經(jīng)成了語法標(biāo)配,Kotlin 協(xié)程相關(guān)的介紹,大家可以參考:https://www.kotlincn.net/docs/reference/coroutines/basics.html
0x2 協(xié)程
協(xié)程是一種在非搶占式多任務(wù)場景下生成可以在特定位置掛起和恢復(fù)執(zhí)行入口的程序組件
協(xié)程的概念在60年代就已經(jīng)提出,目前在服務(wù)端中應(yīng)用比較廣泛,在高并發(fā)場景下使用極其合適,可以極大降低單機的線程數(shù),提升單機的連接和處理能力,但是在移動研發(fā)中,iOS和android目前都不支持協(xié)程的使用
0x3 coobjc 框架
coobjc 是由手機淘寶架構(gòu)團隊推出的能在 iOS 上使用的協(xié)程開發(fā)框架,目前支持 Objective-C 和 Swift 中使用,我們底層使用匯編和 C 語言進(jìn)行開發(fā),上層進(jìn)行提供了 Objective-C 和 Swift 的接口,目前以 Apache 開源協(xié)議進(jìn)行了開源。
0x31 安裝
- cocoapods 安裝:? pod 'coobjc'
- 源碼安裝: 所有代碼在 ./coobjc 目錄下
0x32 文檔
- 閱讀?協(xié)程框架設(shè)計?文檔。
- 閱讀?coobjc Objective-C Guide?文檔。
- 閱讀?coobjc Swift Guide?文檔。
- 閱讀?cokit framework?文檔, 學(xué)習(xí)如何使用系統(tǒng)接口封裝的 api 。
0x33 特性
async/await
- 創(chuàng)建協(xié)程
使用?co_launch
?方法創(chuàng)建協(xié)程
co_launch(^{ ... });
co_launch
?創(chuàng)建的協(xié)程默認(rèn)在當(dāng)前線程進(jìn)行調(diào)度
- await 異步方法
在協(xié)程中我們使用 await 方法等待異步方法執(zhí)行結(jié)束,得到異步執(zhí)行結(jié)果
- (void)viewDidLoad{ ... co_launch(^{ NSData *data = await(downloadDataFromUrl(url)); UIImage *image = await(imageFromData(data)); self.imageView.image = image; }); }
上述代碼將原本需要?dispatch_async
?兩次的代碼變成了順序執(zhí)行,代碼更加簡潔
- 錯誤處理
在協(xié)程中,我們所有的方法都是直接返回值的,并沒有返回錯誤,我們在執(zhí)行過程中的錯誤是通過?co_getError()
?獲取的,比如我們有以下從網(wǎng)絡(luò)獲取數(shù)據(jù)的接口,在失敗的時候, promise 會?reject:error
- (CCOPromise*)co_GET:(NSString*)url parameters:(NSDictionary*)parameters{ CCOPromise *promise = [CCOPromise promise]; [self GET:url parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { [promise fulfill:responseObject]; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { [promise reject:error]; }]; return promise; }
那我們在協(xié)程中可以如下使用:
co_launch(^{ id response = await([self co_GET:feedModel.feedUrl parameters:nil]); if(co_getError()){ //處理錯誤信息 } ... });
生成器
- 創(chuàng)建生成器
我們使用?co_sequence
?創(chuàng)建生成器
COCoroutine *co1 = co_sequence(^{ int index = 0; while(co_isActive()){ yield_val(@(index)); index++; } });
在其他協(xié)程中,我們可以調(diào)用?next
?方法,獲取生成器中的數(shù)據(jù)
co_launch(^{ for(int i = 0; i < 10; i++){ val = [[co1 next] intValue]; } });
- 使用場景
生成器可以在很多場景中進(jìn)行使用,比如消息隊列、批量下載文件、批量加載緩存等:
int unreadMessageCount = 10; NSString *userId = @"xxx"; COSequence *messageSequence = sequenceOnBackgroundQueue(@"message_queue", ^{ //在后臺線程執(zhí)行 while(1){ yield(queryOneNewMessageForUserWithId(userId)); } }); //主線程更新UI co(^{ for(int i = 0; i < unreadMessageCount; i++){ if(!isQuitCurrentView()){ displayMessage([messageSequence take]); } } });
通過生成器,我們可以把傳統(tǒng)的生產(chǎn)者加載數(shù)據(jù)->通知消費者模式,變成消費者需要數(shù)據(jù)->告訴生產(chǎn)者加載模式,避免了在多線程計算中,需要使用很多共享變量進(jìn)行狀態(tài)同步,消除了在某些場景下對于鎖的使用
Actor
_ Actor 的概念來自于 Erlang ,在 AKKA 中,可以認(rèn)為一個 Actor 就是一個容器,用以存儲狀態(tài)、行為、Mailbox 以及子 Actor 與 Supervisor 策略。Actor 之間并不直接通信,而是通過 Mail 來互通有無。_
- 創(chuàng)建 actor
我們可以使用?co_actor_onqueue
?在指定線程創(chuàng)建 actor
CCOActor *actor = co_actor_onqueue(^(CCOActorChan *channel) { ... //定義 actor 的狀態(tài)變量 for(CCOActorMessage *message in channel){ ...//處理消息 } }, q);
- 給 actor 發(fā)送消息
actor 的?send
?方法可以給 actor 發(fā)送消息
CCOActor *actor = co_actor_onqueue(^(CCOActorChan *channel) { ... //定義actor的狀態(tài)變量 for(CCOActorMessage *message in channel){ ...//處理消息 } }, q); // 給actor發(fā)送消息 [actor send:@"sadf"]; [actor send:@(1)];
元組
- 創(chuàng)建元組
使用?co_tuple
?方法來創(chuàng)建元組
COTuple *tup = co_tuple(nil, @10, @"abc"); NSAssert(tup[0] == nil, @"tup[0] is wrong"); NSAssert([tup[1] intValue] == 10, @"tup[1] is wrong"); NSAssert([tup[2] isEqualToString:@"abc"], @"tup[2] is wrong");
可以在元組中存儲任何數(shù)據(jù)
- 元組取值
可以使用?co_unpack
?方法從元組中取值
id val0; NSNumber *number = nil; NSString *str = nil; co_unpack(&val0, &number, &str) = co_tuple(nil, @10, @"abc"); NSAssert(val0 == nil, @"val0 is wrong"); NSAssert([number intValue] == 10, @"number is wrong"); NSAssert([str isEqualToString:@"abc"], @"str is wrong"); co_unpack(&val0, &number, &str) = co_tuple(nil, @10, @"abc", @10, @"abc"); NSAssert(val0 == nil, @"val0 is wrong"); NSAssert([number intValue] == 10, @"number is wrong"); NSAssert([str isEqualToString:@"abc"], @"str is wrong"); co_unpack(&val0, &number, &str, &number, &str) = co_tuple(nil, @10, @"abc"); NSAssert(val0 == nil, @"val0 is wrong"); NSAssert([number intValue] == 10, @"number is wrong"); NSAssert([str isEqualToString:@"abc"], @"str is wrong"); NSString *str1; co_unpack(nil, nil, &str1) = co_tuple(nil, @10, @"abc"); NSAssert([str1 isEqualToString:@"abc"], @"str1 is wrong");
- 在協(xié)程中使用元組
首先創(chuàng)建一個 promise 來處理元組里的值
COPromise* cotest_loadContentFromFile(NSString *filePath){ return [COPromise promise:^(COPromiseFullfill _Nonnull resolve, COPromiseReject _Nonnull reject) { if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { NSData *data = [[NSData alloc] initWithContentsOfFile:filePath]; resolve(co_tuple(filePath, data, nil)); } else{ NSError *error = [NSError errorWithDomain:@"fileNotFound" code:-1 userInfo:nil]; resolve(co_tuple(filePath, nil, error)); } }]; }
然后,你可以像下面這樣獲取元組里的值:
co_launch(^{ NSString *tmpFilePath = nil; NSData *data = nil; NSError *error = nil; co_unpack(&tmpFilePath, &data, &error) = await(cotest_loadContentFromFile(filePath)); XCTAssert([tmpFilePath isEqualToString:filePath], @"file path is wrong"); XCTAssert(data.length > 0, @"data is wrong"); XCTAssert(error == nil, @"error is wrong"); });
使用元組你可以從?await
?返回值中獲取多個值。
- ChatGPT:AI模型框架研究 1次下載
- 【前端開發(fā)】一篇文章概括目前流行的前端開發(fā)框架
- 蘋果ios藍(lán)牙調(diào)試助手工具源代碼下載 7次下載
- Linux內(nèi)核開發(fā)框架學(xué)習(xí)資料匯總 24次下載
- ThinkPHP 6.0完全開發(fā)手冊資源下載 13次下載
- 基于AADL的自主無人系統(tǒng)可成長框架綜述 3次下載
- 一種基于框架特征的共指消解方法 7次下載
- 什么是框架?MATLAB的單元測試框架中文版資料詳細(xì)概述 0次下載
- 如何從一名iOS開發(fā)新手到iOS開發(fā)專家詳細(xì)建議分析 2次下載
- IOS開發(fā)教程之ob<x>jective-C的十個面試題和解答資料免費下載 0次下載
- Java Web開發(fā)教程之Spring框架入門詳細(xì)資料免費下載 14次下載
- AN1292與電機控制應(yīng)用程序框架對比 2次下載
- SSM框架在Web應(yīng)用開發(fā)中的設(shè)計與實現(xiàn) pdf下載 2次下載
- android框架與應(yīng)用開發(fā)介紹 7次下載
- 基于Struts框架和Procedure的Web開發(fā)模式
- 談?wù)?b class="flag-6" style="color: red">協(xié)程的那些事兒 1010次閱讀
- 詳解Linux線程、線程與異步編程、協(xié)程與異步 835次閱讀
- 使用platformio平臺和Arduino框架開發(fā)STM32G0 3012次閱讀
- 聊聊PHP的web應(yīng)用程序開發(fā)框架存在的漏洞有哪些 1561次閱讀
- 使用channel控制協(xié)程數(shù)量 1036次閱讀
- HDF驅(qū)動框架中USB DDK的解析與開發(fā)指導(dǎo) 2000次閱讀
- 方舟開發(fā)框架中容器類的各種類型 1437次閱讀
- 華為推出新聲明式 UI 開發(fā)框架(ArkUI) 4037次閱讀
- 現(xiàn)在流行的Web APP開發(fā)框架有哪些 1.1w次閱讀
- 區(qū)塊鏈應(yīng)用開發(fā)框架Forge介紹 2226次閱讀
- 協(xié)處理器的介紹及應(yīng)用 3859次閱讀
- 手機上的協(xié)處理器有什么作用_蘋果協(xié)處理器是干什么的 2.1w次閱讀
- Python自動化運維之協(xié)程函數(shù)賦值過程 3655次閱讀
- HBase的協(xié)處理器開發(fā)編碼實例 1824次閱讀
- Python中的多核CPU共享數(shù)據(jù)之協(xié)程詳解 6452次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數(shù)據(jù)手冊
- 1.06 MB | 532次下載 | 免費
- 2RK3399完整板原理圖(支持平板,盒子VR)
- 3.28 MB | 339次下載 | 免費
- 3TC358743XBG評估板參考手冊
- 1.36 MB | 330次下載 | 免費
- 4DFM軟件使用教程
- 0.84 MB | 295次下載 | 免費
- 5元宇宙深度解析—未來的未來-風(fēng)口還是泡沫
- 6.40 MB | 227次下載 | 免費
- 6迪文DGUS開發(fā)指南
- 31.67 MB | 194次下載 | 免費
- 7元宇宙底層硬件系列報告
- 13.42 MB | 182次下載 | 免費
- 8FP5207XR-G1中文應(yīng)用手冊
- 1.09 MB | 178次下載 | 免費
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 2555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33566次下載 | 免費
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費
- 4開關(guān)電源設(shè)計實例指南
- 未知 | 21549次下載 | 免費
- 5電氣工程師手冊免費下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費
- 6數(shù)字電路基礎(chǔ)pdf(下載)
- 未知 | 13750次下載 | 免費
- 7電子制作實例集錦 下載
- 未知 | 8113次下載 | 免費
- 8《LED驅(qū)動電路設(shè)計》 溫德爾著
- 0.00 MB | 6656次下載 | 免費
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537798次下載 | 免費
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420027次下載 | 免費
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費
- 6電路仿真軟件multisim 10.0免費下載
- 340992 | 191187次下載 | 免費
- 7十天學(xué)會AVR單片機與C語言視頻教程 下載
- 158M | 183279次下載 | 免費
- 8proe5.0野火版下載(中文版免費下載)
- 未知 | 138040次下載 | 免費
評論
查看更多