如果要研究OpenGL ES相關(guān)和 GPU 相關(guān),這篇文章很具有參考的入門價(jià)值.
十余年的平鄉(xiāng)網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。網(wǎng)絡(luò)營(yíng)銷推廣的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整平鄉(xiāng)建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。成都創(chuàng)新互聯(lián)公司從事“平鄉(xiāng)網(wǎng)站設(shè)計(jì)”,“平鄉(xiāng)網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
首先要從 Runloop 開始說,iOS 的 MainRunloop 是一個(gè)60fps 的回調(diào),也就是說16.7ms(毫秒)會(huì)繪制一次屏幕,這個(gè)時(shí)間段內(nèi)要完成:
這些 CPU 的工作.
然后將這個(gè)緩沖區(qū)交給 GPU 渲染, 這個(gè)過程又包含:
最終現(xiàn)實(shí)在屏幕上.因此,如果在16.7ms 內(nèi)完不成這些操作, eg: CPU做了太多的工作, 或者 view 層次過于多,圖片過于大,導(dǎo)致 GPU 壓力太大,就會(huì)導(dǎo)致"卡"的現(xiàn)象,也就是 丟幀 , 掉幀 .
蘋果官方給出的最佳幀率是: 60fps (60Hz),也就是一幀不丟, 當(dāng)然這是理想中的絕佳體驗(yàn).
一般來說如果幀率達(dá)到 60+fps (fps = 60幀以上,如果幀率fps 50,人眼就基本感覺不到卡頓了,因此,如果你能讓你的 iOS 程序 穩(wěn)定 保持在 60fps 已經(jīng)很不錯(cuò)了, 注釋,是"穩(wěn)定"在60fps,而不是, 10fps , 40fps , 20fps 這樣的跳動(dòng),如果幀頻不穩(wěn)就會(huì)有卡的感覺, 60fps 真的很難達(dá)到, 尤其是在 iPhone 4/4s等 32bit 位機(jī)上,不過現(xiàn)在蘋果已經(jīng)全面放棄32位,支持最低64位會(huì)好很多.
總的來說, UIView從繪制到Render的過程有如下幾步:
UIView 的繪制和渲染是兩個(gè)過程:
上面提到的從 CPU 到 GPU 的過程可用下圖表示:
下面具體來討論下這個(gè)過程
假設(shè)我們創(chuàng)建一個(gè) UILabel
這個(gè)時(shí)候不會(huì)發(fā)生任何操作, 由于 UILabel 重寫了 drawRect 方法,因此,這個(gè) View 會(huì)被 marked as "dirty" :
類似這個(gè)樣子:
然后一個(gè)新的 Runloop 到來,上面說道在這個(gè) Runloop 中需要將界面渲染上去,對(duì)于 UIKit 的渲染,Apple用的是它的 Core Animation 。 做法是在Runloop開始的時(shí)候調(diào)用:
在 Runloop 結(jié)束的時(shí)候調(diào)用
在 begin 和 commit 之間做的事情是將 view 增加到 view hierarchy 中,這個(gè)時(shí)候也不會(huì)發(fā)生任何繪制的操作。 當(dāng) [CATransaction commit] 執(zhí)行完后, CPU 開始繪制這個(gè) view :
首先 CPU 會(huì)為 layer 分配一塊內(nèi)存用來繪制 bitmap ,叫做 backing store
創(chuàng)建指向這塊 bitmap 緩沖區(qū)的指針,叫做 CGContextRef
通過 Core Graphic 的 api ,也叫 Quartz2D ,繪制 bitmap
將 layer 的 content 指向生成的 bitmap
清空 dirty flag 標(biāo)記
這樣 CPU 的繪制基本上就完成了.
通過 time profiler 可以完整的看到個(gè)過程:
假如某個(gè)時(shí)刻修改了 label 的 text :
由于內(nèi)容變了, layer 的 content 的 bitmap 的尺寸也要變化,因此這個(gè)時(shí)候當(dāng)新的 Runloop 到來時(shí), CPU 要為 layer 重新創(chuàng)建一個(gè) backing store ,重新繪制 bitmap .
CPU 這一塊最耗時(shí)的地方往往在 Core Graphic 的繪制上,關(guān)于 Core Graphic 的性能優(yōu)化是另一個(gè)話題了,又會(huì)牽扯到很多東西,就不在這里討論了.
GPU bound:
CPU 完成了它的任務(wù):將 view 變成了 bitmap ,然后就是 GPU 的工作了, GPU 處理的單位是 Texture .
基本上我們控制 GPU 都是通過 OpenGL 來完成的,但是從 bitmap 到 Texture 之間需要一座橋梁, Core Animation 正好充當(dāng)了這個(gè)角色:
Core Animation 對(duì) OpenGL 的 api 有一層封裝,當(dāng)我們要渲染的 layer 已經(jīng)有了 bitmap content 的時(shí)候,這個(gè) content 一般來說是一個(gè) CGImageRef , CoreAnimation 會(huì)創(chuàng)建一個(gè) OpenGL 的 Texture 并將 CGImageRef(bitmap) 和這個(gè) Texture 綁定,通過 TextureID 來標(biāo)識(shí)。
這個(gè)對(duì)應(yīng)關(guān)系建立起來之后,剩下的任務(wù)就是 GPU 如何將 Texture 渲染到屏幕上了。 GPU 大致的工作模式如下:
整個(gè)過程也就是一件事:
CPU 將準(zhǔn)備好的 bitmap 放到 RAM 里, GPU 去搬這快內(nèi)存到 VRAM 中處理。 而這個(gè)過程 GPU 所能承受的極限大概在16.7ms完成一幀的處理,所以最開始提到的60fps其實(shí)就是GPU能處理的最高頻率.
因此, GPU 的挑戰(zhàn)有兩個(gè):
這兩個(gè)中瓶頸基本在第二點(diǎn)上。渲染 Texture 基本要處理這么幾個(gè)問題:
Compositing 是指將多個(gè)紋理拼到一起的過程,對(duì)應(yīng) UIKit ,是指處理多個(gè) view 合到一起的情況,如:
如果 view 之間沒有疊加,那么 GPU 只需要做普通渲染即可.
如果多個(gè) view 之間有疊加部分, GPU 需要做 blending .
加入兩個(gè) view 大小相同,一個(gè)疊加在另一個(gè)上面,那么計(jì)算公式如下:
R = S + D *( 1 - Sa )
其中 S , D 都已經(jīng) pre-multiplied 各自的 alpha 值。
Sa 代表 Texture 的 alpha 值。
假如 Top Texture (上層 view )的 alpha 值為 1 ,即不透明。那么它會(huì)遮住下層的 Texture .
即, R = S 。是合理的。
假如 Top Texture (上層 view )的 alpha 值為 0.5 ,
S 為 (1,0,0) ,乘以 alpha 后為 (0.5,0,0) 。
D 為 (0,0,1) 。
得到的 R 為 (0.5,0,0.5) 。
基本上每個(gè)像素點(diǎn)都需要這么計(jì)算一次。
因此, view 的層級(jí)很復(fù)雜,或者 view 都是半透明的( alpha 值不為 1 )都會(huì)帶來 GPU 額外的計(jì)算工作。
這個(gè)問題,主要是處理 image 帶來的,假如內(nèi)存里有一張 400x400 的圖片,要放到 100x100 的 imageview 里,如果不做任何處理,直接丟進(jìn)去,問題就大了,這意味著, GPU 需要對(duì)大圖進(jìn)行縮放到小的區(qū)域顯示,需要做像素點(diǎn)的 sampling ,這種 smapling 的代價(jià)很高,又需要兼顧 pixel alignment 。 計(jì)算量會(huì)飆升。
如果我們對(duì) layer 做這樣的操作:
會(huì)產(chǎn)生 offscreen rendering ,它帶來的最大的問題是,當(dāng)渲染這樣的 layer 的時(shí)候,需要額外開辟內(nèi)存,繪制好 radius,mask ,然后再將繪制好的 bitmap 重新賦值給 layer 。
因此繼續(xù)性能的考慮, Quartz 提供了優(yōu)化的 api :
簡(jiǎn)單的說,這是一種 cache 機(jī)制。
同樣 GPU 的性能也可以通過 instrument 去衡量:
紅色代表 GPU 需要做額外的工作來渲染 View ,綠色代表 GPU 無需做額外的工作來處理 bitmap 。
全文完
收錄: 原文地址
oc已全部翻譯完成視頻總4個(gè)視頻免費(fèi)下載
鏈接:
提取碼:64s9
oc已全部翻譯完成視頻 總4個(gè)視頻|OC教程04:速建+講解.mp4|OC教程03:如何給機(jī)器人添加紋理與著色.mp4|OC教程02:場(chǎng)景管理.mp4|OC教程01:涂鴉的投射原理與應(yīng)用.mp4
篇一:分享簡(jiǎn)單學(xué)習(xí)iOS開發(fā)的方法
隨著3G技術(shù)的普及與智能終端的快速發(fā)展,逐漸的移動(dòng)開發(fā)者最受企業(yè)的歡迎,特別是iOS軟件開發(fā)人才更是得到了企業(yè)的青睞,從現(xiàn)在情況來看,iOS培訓(xùn)和iOS軟件開發(fā)人才有些嚴(yán)重供不應(yīng)求。
容易上手的,學(xué)習(xí)iOS要注意到每個(gè)細(xì)節(jié),因?yàn)槊總€(gè)細(xì)小的知識(shí)都有可能改變這個(gè)程序,如果有一點(diǎn)的錯(cuò)誤都會(huì)導(dǎo)致整個(gè)程序無法運(yùn)行,其實(shí)學(xué)習(xí)iOS和上學(xué)學(xué)習(xí)一樣,都是從最基礎(chǔ)的開始學(xué)起,慢慢的積累知識(shí)。如果想學(xué)好iOS,現(xiàn)在單單在網(wǎng)上學(xué)習(xí)是有點(diǎn)out了,可以選擇零學(xué)費(fèi),就能夠入學(xué)的培訓(xùn)學(xué)校學(xué)習(xí)一下,如果沒有合適的話,可以了解一下培訓(xùn)機(jī)構(gòu),找一個(gè)口碑不錯(cuò)的,這樣結(jié)合理論和實(shí)際才能夠?qū)W好iOS。
在課前一定要做好準(zhǔn)備資料及準(zhǔn)備內(nèi)容,要知道老師要講什么?先做好預(yù)習(xí),這樣有準(zhǔn)備的上戰(zhàn)場(chǎng)才會(huì)學(xué)得更好,在課堂上認(rèn)真聽老師講課,在電腦上操作老師所講的內(nèi)容,如果有不懂的一定要及時(shí)向講師問清是怎么回事,課后多做幾次練習(xí),那么就不是問題了。3
如果聽不懂怎么辦?
這些現(xiàn)象很正常,誰也不敢保證講師所講的知識(shí)都能夠無一不漏的聽明白,能夠在電腦上操作出來,那么如果遇到不懂得就要直接問,還可以先預(yù)習(xí)今后再去學(xué)習(xí)理論課的時(shí)分就能夠有對(duì)于性的去聽了,教師講到你現(xiàn)已把握的內(nèi)容時(shí),你能夠注意聽一下講師是不是有了新的見解及創(chuàng)新的認(rèn)識(shí)、講的和你了解到的是不是一樣,如果不太一樣的話,那么就要做下記號(hào),課下與老師溝通,承認(rèn)這個(gè)
常識(shí)點(diǎn)的真實(shí)意義;若是講到你預(yù)習(xí)時(shí)不會(huì)的常識(shí)點(diǎn)的話,你更大概仔細(xì)的去聽了,認(rèn)真的去了解一下到底是怎么個(gè)意思?
篇二:如何快速學(xué)會(huì)ios開發(fā)
針對(duì)學(xué)習(xí)iOS開發(fā)怎么樣?想學(xué)iOS開發(fā)如何才能快速學(xué)習(xí)?沒有基礎(chǔ)怎么快速學(xué)習(xí)iOS開發(fā)等問題,藍(lán)鷗iOS培訓(xùn)專業(yè)老師指點(diǎn)明燈!看著身邊學(xué)iOS開發(fā)的人拿了高工資,很多人按捺不住了。但菜鳥真的也可以成為iOS開發(fā)軟件工程師嗎?只要有恰當(dāng)?shù)膶W(xué)習(xí)方法,學(xué)習(xí)軟件開發(fā)并不難。對(duì)于軟件初學(xué)者來說,主要做到以下幾點(diǎn):
一、打好基礎(chǔ),不能一步登天
學(xué)習(xí)iOS,首先要學(xué)習(xí)C語言,很多人跳過C,直接學(xué)Objective-C,這是極不可取的。Objective-C是C的超集,必須有C的基礎(chǔ),學(xué)習(xí)才能更好更快的進(jìn)行。不要一開始就盲目崇拜別人的大項(xiàng)目,要從小項(xiàng)目開始,一步一個(gè)腳印,遇到困難不要退縮,解決困難也是學(xué)習(xí)的過程。
二、必須如蜜蜂,多方采集花蜜
在學(xué)習(xí)初期對(duì)于iOS沒有概念,最好的辦法就是多看別人的代碼,多吸取別人的養(yǎng)分。遇到不懂得問題不要跳過,而是要多問,多向人請(qǐng)教,學(xué)習(xí)別人的思路,吸取有益的知識(shí),并做好學(xué)習(xí)筆記。積少成多,會(huì)成為你不小的財(cái)富。
三、勤動(dòng)腦,多動(dòng)手,有創(chuàng)新精神
軟件開發(fā)者是為了讓軟件實(shí)現(xiàn)更豐富更強(qiáng)大的功能,必須有很強(qiáng)的實(shí)際操作能力。作為iOS開發(fā)工程師,不但要了解用戶需要哪些功能,有哪些需求,還要多動(dòng)腦,開發(fā)出符合市場(chǎng)以及時(shí)代需求的項(xiàng)目。這都需要軟件開發(fā)者具備很好創(chuàng)新精神。
由此可見,學(xué)習(xí)iOS開發(fā),只要肯吃苦,有恒心,菜鳥也可以有很藍(lán),很廣闊的天空。iOS培訓(xùn)很注重基礎(chǔ)教學(xué),教學(xué)方式與大學(xué)不同,在教授理論知識(shí)的同時(shí),更注重實(shí)踐技能的培養(yǎng)。擺正心態(tài),切勿操之過急,囫圇吞棗,將每天所學(xué)定義為就是今后工作要用的,這樣你便會(huì)認(rèn)真對(duì)待每一次學(xué)習(xí)、每一行代碼和遇到的每一個(gè)難題。
參加iOS開發(fā)培訓(xùn)也可以,現(xiàn)在iOS開發(fā)培訓(xùn)大概也就4個(gè)月時(shí)間,花一兩萬系統(tǒng)學(xué)4個(gè)月也是一個(gè)不錯(cuò)的選擇,雖然要一兩萬,但是效果跟自己學(xué)肯定是不一樣的,要是自己學(xué)跟有老師帶著學(xué)一樣,那這個(gè)世界上將沒有學(xué)校存在了。對(duì)于參加iOS開發(fā)培訓(xùn)的一定
要選對(duì)機(jī)構(gòu),有句話說得好,選對(duì)比選好有時(shí)候重要太多。你考30分的'成績(jī)讓你去北大清華也不一定能夠成就了呢,所以選擇口碑好的機(jī)構(gòu),專注iOS開發(fā)的機(jī)構(gòu)比較好,畢竟咱基礎(chǔ)不好,那些機(jī)構(gòu)做雜很難做精。不管是快速學(xué)還是慢慢自學(xué)還是選擇iOS培訓(xùn)機(jī)構(gòu)系統(tǒng)培訓(xùn),只要你投入進(jìn)去就好,堅(jiān)持下去一定會(huì)有大收獲。不管做什么或者學(xué)什么一定要避免三天打魚兩天曬網(wǎng),這樣效果不會(huì)明顯。
篇三:零基礎(chǔ)學(xué)iOS開發(fā)的方法
怎么學(xué)習(xí)iOS開發(fā),尤其是對(duì)于沒有基礎(chǔ)的,甚至是0基礎(chǔ)的朋友而言,要學(xué)習(xí)iOS開發(fā)就需要注重方法了。由于iphone手機(jī)帶來的手機(jī)應(yīng)用狂潮,現(xiàn)在很多人都希望從事這塊的開發(fā)。很多初學(xué)者可能會(huì)問,沒有基礎(chǔ)怎么樣才能學(xué)好iOS開發(fā),我們要看什么書呢,還是什么視頻,其實(shí)這些都不是重要的,重要的是,你認(rèn)為自己可以學(xué)好iOS開發(fā),認(rèn)為自己可以堅(jiān)持下來,這是關(guān)鍵啦。
其實(shí)學(xué)很多語言都是通的,即使0基礎(chǔ)學(xué)習(xí)也不怕,從C語言入門,因?yàn)閕OS開發(fā)用的是OC語言,是在C基礎(chǔ)上的,不過也跟C不是很搭界,你可以直接學(xué)習(xí)OC語言也可以,還有開發(fā)工具是用Xcode,是在Mac系統(tǒng)的,你多摸索一下就可以開發(fā)簡(jiǎn)單的應(yīng)用了,建議你買一本iphone開發(fā)秘籍第二版看看。學(xué)語言,無非就是要學(xué)好基礎(chǔ),弄清楚概念,然后做個(gè)簡(jiǎn)單的例子,慢慢的體會(huì),基礎(chǔ)打好了,到后面你會(huì)覺得突然自己提高了很多,很多東西都自然而然地明白了,在黑暗中的努力是為了迎接光明。
我覺得學(xué)iOS開發(fā),首先心態(tài)要好,不要想著我已經(jīng)學(xué)習(xí)很長(zhǎng)時(shí)間了,可以找個(gè)好工作,可以賺錢了,牛人除外,不過大多都是普通人。
先慢慢培養(yǎng)興趣下定決心,然后開始找資料,找視頻,查百度。等你覺得這些基礎(chǔ)的都差不多理解了,那就別看書,將精力集中于界面開發(fā)、一定的數(shù)據(jù)庫開發(fā)、通訊接口開發(fā)、協(xié)同開發(fā)與聯(lián)調(diào)。然后自己設(shè)計(jì)個(gè)東西,可以涵蓋他們的,做個(gè)自己想做的東西出來,雖然可能很難,但是你會(huì)在過程中學(xué)到很多,是別人教不會(huì)你的。
在學(xué)習(xí)過程中遇到什么問題,你可以百度一下看看別人的回答,看多了印象就深了,也就慢慢掌握了。遇到什么思路上的問題,可以來藍(lán)鷗網(wǎng)站技術(shù)論壇發(fā)帖,論壇肯定會(huì)有人來幫忙的,就算不能完全解決,也可以提供點(diǎn)參考。學(xué)習(xí)要會(huì)利用資源,論壇上那么好的資源不用可惜的哦,還有資料堆的東西,只要你能掌握70%,不相信你可以試試。
記錄器
基于不同的場(chǎng)景提供關(guān)于記錄的封裝、適配。一般分為頁面式,流式,自定義式。
記錄管理者
管理統(tǒng)計(jì)記錄數(shù)據(jù),包含記錄緩存,磁盤存儲(chǔ),上傳器。
如何降低數(shù)據(jù)的丟失率?
兩種解決方案:
記錄上傳的時(shí)機(jī)
上傳時(shí)機(jī)的選擇
從三個(gè)方面分析架構(gòu)設(shè)計(jì):整體架構(gòu)、數(shù)據(jù)流、反向更新。
View 的功能包含:控件的初始化、設(shè)置數(shù)據(jù)、交互事件代理等。
ViewController 的功能:視圖創(chuàng)建與組合、協(xié)調(diào)邏輯、事件回調(diào)處理等,事件回調(diào)處理指的是視圖層的事件。
業(yè)務(wù)邏輯處理(預(yù)排版)、數(shù)據(jù)增刪改查封裝者、線程安全處理。
網(wǎng)絡(luò)請(qǐng)求、數(shù)據(jù)解析、增刪改查、本地處理邏輯(適配)
數(shù)據(jù)流包含:網(wǎng)絡(luò)數(shù)據(jù)、業(yè)務(wù)數(shù)據(jù)、UI數(shù)據(jù)三部分。
網(wǎng)絡(luò)數(shù)據(jù)經(jīng)過 Engine 層處理加工產(chǎn)生業(yè)務(wù)數(shù)據(jù),業(yè)務(wù)數(shù)據(jù)經(jīng)過 ViewModel 層處理產(chǎn)生UI數(shù)據(jù),UI數(shù)據(jù)會(huì)轉(zhuǎn)交給視圖控制器控制視圖的顯示。
用戶交互網(wǎng)絡(luò)刷新等都會(huì)導(dǎo)致視圖層變化,通過代理方式通知視圖控制器。控制器對(duì)ViewModel的強(qiáng)引用找到對(duì)應(yīng)ViewModel,然后通過UI數(shù)據(jù)對(duì)業(yè)務(wù)數(shù)據(jù)的弱引用找到對(duì)應(yīng)的業(yè)務(wù)數(shù)據(jù)同時(shí)打上臟標(biāo)記。最后ViewModel進(jìn)行數(shù)據(jù)流的重新驅(qū)動(dòng),將臟數(shù)據(jù)重新處理生成新的UI數(shù)據(jù)更新視圖。
本節(jié)梳理時(shí)長(zhǎng)統(tǒng)計(jì)實(shí)現(xiàn)原理和復(fù)雜頁面的架構(gòu)實(shí)現(xiàn)思路。
這篇文章主要介紹了實(shí)際應(yīng)用 MVVM 的過程中的一些問題和解決方案
MVVM(Model View ViewModel)是一種 MVC(Model View Controller)的一種變型,來解決 MVC 中龐大復(fù)雜的 Controller 難以維護(hù)的問題。大致上講 MVVM 有幾個(gè)要求:
MVVM 和 MVC 有很多類似的特點(diǎn),主要的不同有:
另外一點(diǎn),MVVM 默認(rèn) View 和 View Controller 有一個(gè)一對(duì)一的關(guān)系,一般我們把這兩個(gè)看做一個(gè)整體,會(huì)以 .swift 文件 和 Storyboard 的形式出現(xiàn)。
View Model 的工作是處理所有的展示數(shù)據(jù)的邏輯。如果一個(gè) model 中有一個(gè) NSDate 對(duì)象, NSDateFormatter 就會(huì)在 View Model 中用來設(shè)置日期的展示形式。
View Model 不能接觸任何用戶界面的部分,View Model 文件中不應(yīng)該 import UIKit ,View Controller 會(huì)觀察 View Model 去了解什么時(shí)候顯示新的數(shù)據(jù)(通過 KVO 或者 FRP(Functional Reactive Programming))
MVVM 和 MVC 有一個(gè)共同的弱點(diǎn):沒有清楚的定義應(yīng)該把網(wǎng)絡(luò)請(qǐng)求部分放在哪里。在實(shí)際操作過程中,我會(huì)把網(wǎng)絡(luò)請(qǐng)求放在 View Model 文件里面,但之后我打算把網(wǎng)絡(luò)請(qǐng)求放在自己獨(dú)立的一個(gè)類中,View Model 文件會(huì)擁有這個(gè)對(duì)象。
下面我們主要談一談實(shí)際應(yīng)用 MVVM 過程中一些挑戰(zhàn):
例如你想構(gòu)造這樣一個(gè)常用的界面,有一個(gè) segment control 在屏幕頂部,屏幕的其他部分是一個(gè) collection view,選擇不同的 segment,就會(huì)展示不同樣式的 collection view,元素的排列順序。我們定義了一個(gè) enum 來枚舉所有的排列樣式:
那么這個(gè) enum 在 MVVM 模式中應(yīng)該放在哪里呢?因?yàn)檫@個(gè) enum 決定了數(shù)據(jù)排列的順序,每個(gè) cell 中的文字和按鈕的 title,這些都屬于展示的邏輯,所以這個(gè) enum 看起來應(yīng)該放在 view model 中。
然而,這些 layout 并不改變要展示的數(shù)據(jù),只是決定了要呈現(xiàn)的數(shù)據(jù)的排列方式和排列順序,從這個(gè)角度上來說 enum 又應(yīng)該放在 view controller 中。
我的解決方法是把 enum 放在 view model 中,然后在 view model 中加一個(gè)對(duì)外的 Observable 或者 Signal 來表示使用了哪個(gè) layout,基于用戶選擇的 segment,view model 更新這個(gè)值,然后在 view controller 中根據(jù)相應(yīng)的 layout 改變 collection view 的樣式,view controller 也可以根據(jù)這個(gè)值來決定用哪個(gè) cell reuse identifier
iOS 開發(fā)者在用 MVVM 和 FRP 寫應(yīng)用的時(shí)候最常見的問題可能就是 ViewModel 怎么把數(shù)據(jù)展現(xiàn)給 ViewController。當(dāng) Model 層的數(shù)據(jù)發(fā)生變化更新的時(shí)候,ViewController 需要得到通知然后做出相應(yīng)的 UI 更新,我們一般會(huì)用到兩種機(jī)制:
第一個(gè)選項(xiàng)很吸引人,因?yàn)榭梢栽?View Controller 中決定怎么選擇觀察那些 property。然而,我不推薦在 Swift 中使用第一個(gè)選項(xiàng),因?yàn)?Swift 在 KVO 中沒有類型檢查,你需要對(duì) AnyObject 強(qiáng)制轉(zhuǎn)換類型很多次。
第二個(gè)選項(xiàng)是比較 Swift 的方式,基于 Swift 的 generics 特性,signals,sequences,observables 可以支持編譯過程中的類型檢查。
但有時(shí)候在 view model 增加這些 Signals 或者 Observables 有些困難。Swift 的初始化方法對(duì)于什么時(shí)候?qū)?property 賦值有非常明確的規(guī)定。Signals 或者 Observables 需要使用 view model 內(nèi)部的狀態(tài),所以它們必須在 super.init() 之后才能創(chuàng)建,但是另一方面,我們?cè)谡{(diào)用 super.init() 之前保證所有 property 已經(jīng)被賦值了,包括那些 Signal/Observable property。
這是個(gè)先有雞還是先有蛋的問題。
我采用比較簡(jiǎn)單的解決方法:定義成 var 的隱式可選類型,這樣就可以在 super.init() 之后才給 property 賦值。這不是一個(gè)完美的解決辦法。我們可以用 lazy var property 的閉包賦值來代替上面的方法。在 Swift 不斷完善和更新的過程中,大家也可以探索其他更好的辦法。
舉一個(gè)很常用的例子,用戶點(diǎn)擊 collection view 中的一個(gè) cell,跳轉(zhuǎn)到詳情頁面。用戶點(diǎn)擊的操作應(yīng)該在 view controller 中處理,具體內(nèi)容是展現(xiàn)一個(gè)新的詳情頁面。但是 view controller 不能直接接觸 models,我們要如何用 MVVM 模式實(shí)現(xiàn)這樣的用戶交互呢?
我的解決方案是利用 Swift 的閉包。首先在 view model 中定義一個(gè)閉包:
然后在 view model 中添加一個(gè) property:
接著我需要調(diào)用閉包,在 view model 中定義一個(gè)view controller 可以調(diào)用的函數(shù),這個(gè)函數(shù)的參數(shù)是可以決定使用什么數(shù)據(jù),一般情況下常用 index path:
現(xiàn)在當(dāng)用戶選中一個(gè) cell,會(huì)調(diào)用 view model 中的這個(gè)函數(shù),并且傳入 index path 參數(shù),view model 決定使用哪個(gè)數(shù)據(jù),并調(diào)用在 view controller 中定義的閉包,例如:
最后一個(gè)問題是怎么創(chuàng)建這個(gè) view model。我們需要傳遞一個(gè)閉包給view model 的初始化函數(shù),然后用 lazy loading 來調(diào)用 view model 的初始化函數(shù)。
MMKV是微信開源的數(shù)據(jù)持久化框架,現(xiàn)在已經(jīng)支持Android/iOS/PC 平臺(tái)。該框架是基于mmap映射內(nèi)存的key—value組件,使用protobuf實(shí)現(xiàn)數(shù)據(jù)的序列化和反序列化,性能高,穩(wěn)定性強(qiáng)。微信在2015就在微信應(yīng)用上使用了該框架。實(shí)驗(yàn)證明MMKV是數(shù)據(jù)持久化的首選。
ProtoBuf是由google公司用于數(shù)據(jù)交換的序列結(jié)構(gòu)化數(shù)據(jù)格式,具有跨平臺(tái)、跨語言、可擴(kuò)展特性,類型于常用的XML及JSON,但具有更小的傳輸體積、更高的編碼、解碼能力,特別適合于數(shù)據(jù)存儲(chǔ)、網(wǎng)絡(luò)數(shù)據(jù)傳輸?shù)葘?duì)存儲(chǔ)體積、實(shí)時(shí)性要求高的領(lǐng)域。
優(yōu)點(diǎn):空間效率搞,時(shí)間效率要高,對(duì)于數(shù)據(jù)大小敏感,傳輸效率高的。
缺點(diǎn):消息結(jié)構(gòu)可讀性不高,目前使用不廣泛。
MMKV維護(hù)了一個(gè)String,AnyObject的dic,在寫入數(shù)據(jù)時(shí),會(huì)在dit和mmap映射區(qū)寫入相同的數(shù)據(jù),最后由內(nèi)核同步到文件。因?yàn)閐ic和文件數(shù)據(jù)同步,所以讀取時(shí)直接去dit中的值。MMKV數(shù)據(jù)持久化的步驟:mmap 內(nèi)存映射 - 寫數(shù)據(jù) - 讀數(shù)據(jù) - crc校驗(yàn) - aes加密。
在MMKV的源碼中,是怎么樣內(nèi)存映射的呢?