iOS 摸鱼周报 #54 | Apple 辅助功能持续创新
本期概要
- 話題:Apple 在輔助功能上持續創新;IAP 自動續訂提價通知更新
- 面試模塊:學習 OOMDetector 中的 CRC64 應用實踐
- 優秀博客:iOS 內存
- 學習資料:一份英語進階指南
- 開發工具:一款 macOS 上的 純文本編輯器 CotEditor
本期話題
Apple 在輔助功能上的又一創新
@zhangferry:作為一款受眾非常廣的產品,針對特殊人群的輔助功能就顯得尤為重要,不得不說 Apple 對輔助功能的重視程度和探索精神都是值得尊敬的。最近 Apple 又公布了一些基于軟硬件和機器學習帶來的輔助功能提升。
針對盲人和視力障礙的人群:Apple 基于配有 LiDAR 的設備可以探測到前方是否有門,門距離自己有多遠,甚至要通過推還是拉的方式開門都能識別出來。
針對行動不便的人群:有一項 iPhone 結合 Apple Watch 的功能,借助于 Apple Watch 的 Mirroring 功能,可以用手機遠程操作 Apple Watch。同時 Apple Watch 也有提升,通過 AssistiveTouch 技術,可以讓 Apple Watch 識別特定手勢,像是手指兩次捏合的手勢可以用于接電話、拍照、暫停音樂等。
針對聽力障礙的人群:在 iPhone、iPad、Mac 配備了實時字幕功能,不只是針對 Facetime,對于任意音頻內容,包括外部 App 都可以使用。樣式是在設備頂部展示一個文本轉義框,字體大小還可調整。
同時 VoiceOver 也進一步完善,增加了 20 多個地區語言的支持。
IAP 自動續訂提價通知更新
@zhangferry:自動續訂是 Apple Store 付費產品使用最廣泛的一個訂閱選項。當一個已經被用戶續訂的產品進行提價時,Apple 會通過郵件、推送和 App 內消息的形式告知用戶,如果用戶未選擇接受變更價格,下個續訂周期就會默認中斷。這可能會導致部分用戶的不理解,影響其體驗。該項改進意在增加一些條件,使得提價之后的續訂周期可以默認延續。這個條件是:每年提價不超過一次,同時訂閱價格上調不超過 5 美元和 50%,或者年度訂閱價格上調不超過 50 美元和 50%,并且是在法律允許的范圍內。該舉措仍會通知到用戶價格的變更。
面試解析
整理編輯:Hello World
學習 OOMDetector 中的 CRC64 應用實踐
以 OOMDetector 中對 CRC64 的應用講解實際應用時的一些變體操作。示例代碼如下:
```cpp
define POLY64REV 0x95AC9329AC4BC9B5ULL
static uint64t crctable[8][256];
void initcrctableforoom(void) { uint64t c; int n, k; static int first = 1; if(first) { first = 0; // 針對單個字節值生成單表 for (n = 0; n < 256; n++) { c = (uint64t)n; for (k = 0; k < 8; k++) { // LSB 右移生成邏輯, 主要適用于小端模式 f (c & 1) c = (c >> 1) ^ POLY64REV; else c >>= 1; } crctable[0][n] = c; } // 生成不同權重的 CRC 值 for (n = 0; n < 256; n++) { c = crctable[0][n]; for (k = 1; k < 8; k++) { c = crctable[0][c & 0xff] ^ (c >> 8); crctable[k][n] = c; } } } }
uint64t rapidcrc64(uint64t crc, const char *buf, uint64t len) { register uint64t *buf64 = (uint64t *)buf; register uint64t c = crc; register uint64t length = len; // 取反 c = ~c; while (length >= 8) { c ^= *buf64++; // 根據不同權重的字節數據查表 c = crctable[0][c & 0xff] ^ crctable[1][(c >> 8) & 0xff] ^ \ crctable[2][(c >> 16) & 0xff] ^ crctable[3][(c >> 24) & 0xff] ^\ crctable[4][(c >> 32) & 0xff] ^ crctable[5][(c >> 40) & 0xff] ^\ crctable[6][(c >> 48) & 0xff] ^ crctable[7][(c >> 56) & 0xff]; length -= 8; } // 這里注釋的內容,是單字節計算的邏輯,即每次計算一個字節,可能最早的 OOMDetector 采用的是該計算方式。 // buf = (char *)buf64; // while (length > 0) { // crc = (crc >> 8) ^ crc_table[0][(crc & 0xff) ^ *buf++]; // length--; // } // 取反 c = ~c; return c; } ```
主要有兩步操作,CRC 生成表以及 CRC 查表。以這兩步出發學習一下 CRC 實際應用中的變體以及目的。
生成表-多表級聯
有別于《#53 周報》中的單表查詢方式,OOMDetector將 crc_table定義為crc_table[8][256]二維矩陣的多表查詢。其中單維度的表仍然以字節大小(8 bit)作為位寬生成,即單個表大小為 2 ^ 8 = 256,crc_table[8]表示不同權重的單表, 這種方式稱為 CRC 位域多表查詢 。
CRC 位域多表查表方法與傳統的 CRC 查表方法最大的不同在于多表級聯壓縮表格空間。
如果是傳統單表查詢,一次性查詢雙字節數據的 CRC,需要單表大小為 256 * 256,采用多表級聯只需要 2 *256,實現了極大的空間壓縮。
更詳細的原理可以參考《CRC位域多表查表方法》,這里只理解該優化依賴的核心性質:crc_table[A ^ B] = crc_table[A] ^ crc_table[B]。
從 CRC 計算的本質出發,其實就是依次的計算每一 bit 位的余數,而余數的結果值,只和 POLY計算的次數和順序有關。
我們以示例 0xBC來拆解這個計算過程:
采用右移的計算方式,左移和右移的區別在下小結中講解。1011 1010(0xBA) 計算 CRC Table 簡化為:
cpp 1011 1010 ^ (poly ^ 0>>1 ^ poly>>2 ^ poly>>3 ^ poly>>4 ^ 0>>5 ^ poly>>6 ^ 0>>7)
現在 0xBA 根據異或性質分解為 0xB0 ^ 0x0A。
我們單獨計算 0xB0 和 0x0A的 CRC 值,來看他們的計算過程 ```cpp 0xB0 = 0b 1011 0000; CRC[0xB0] = 1011 0000 ^ (poly ^ 0>>1 ^ poly>>2 ^ poly>>3 ^ 0>>4 ^ 0>>5 ^ 0>>6 ^ 0>>7);
0x0A = 0b 0000 1010; CRC[0x0A] = 0000 1010 ^ (0 ^ 0>>1 ^ 0>>2 ^ 0>>3 ^ poly>>4 ^ 0>>5 ^ poly>>6 ^ 0>>7) ```
上面兩個公式做異或,最終結果值和 CRC[0xBA]相等
```cpp CRC[0xB0] ^ CRC[0x0A] = 1011 0000 ^ (poly ^ 0>>1 ^ poly>>2 ^ poly>>3 ^ 0>>4 ^ 0>>5 ^ 0>>6 ^ 0>>7) ^ 0000 1010 ^ (0 ^ 0>>1 ^ 0>>2 ^ 0>>3 ^ poly>>4 ^ 0>>5 ^ poly>>6 ^ 0>>7);
// 由于 0 異或任何值還是原值,結果可以簡化為: 1011 0000 ^ 0000 1010 ^ (poly ^ 0>>1 ^ poly>>2 ^ poly>>3 ^ poly>>4 ^ 0>>5 ^ poly>>6 ^ 0>>7); ```
即證明 CRC 性質:crc_table[A ^ B] = crc_table[A] ^ crc_table[B]成立。
CRC 級聯查表另一個需要解決的就是多字節數據的權重問題,上面證明了 CRC 性質可行性,但是在查表時為了方便,使用的索引并非是直接拆解的數據,例如 CRC[0x AA BB] = CRC[0x AA 00] ^ CRC[0xBB] ,兩次查表索引分別為 0xBB 和0xAA,并非是 0xBB 和 0xAA 00。
權重就是指的由 CRC[0xAA] 計算 CRC[0xAA 00] ... CRC[0xAA 00 00 00 00 00 00 00] 等數據,實現也很簡單,可以看做是已知單表crc_table[256]的值,求數據的值,即 init_crc_table_for_oom()中第二個 for 的目的。
生成表-單表反向計算(reversed)
OOMDetector 生成單表時區別于傳統的 MSB 左移(<<) 計算方式,采用的是 LSB 右移(>>) 生成方式。原因是 iOS 的主機字節序是小端模式,但是一般規范中要求數據在網絡傳輸過程中采用網絡字節序(大端模式)。
一個系統中針對每一個字節內的 bit 位也是有順序的,稱為位序。
位序一般和主機字節序是一致的,例如一個數據 0x11 22 在 iOS 內存中的存儲為 0x22 0x11,實際 0x11 = 0b 0001 0001的存儲順序也是逆序的,表示為 0b 1000 1000。
為了按照網絡字節序傳輸規范作為計算 CRC 順序的依據,小端的機器上在使用 CRC 時都采用右移計算,即 0b 1000 1000按照右移順序依次計算 0 0 0 1 0 0 0 1,這樣保證了規范性,無論其他 server 接收端是大端模式還是小端模式,在拿到數據后自己按照主機字節序重新計算即可。
反向計算最重要的一點:由于計算順序反向,所以 POLY生成多項式的值相對于傳統給定的生成多項式值,也要做位序的反向生成新的 POLY值。
查表
在 rapid_crc64()查表中一次計算了 8 字節數據的 CRC 值,根據crc_table[A ^ B] = crc_table[A] ^ crc_table[B]性質,查表操作以對應權重的字節數據在相應的級聯表中查找值即可,具體到每一個級聯表,和單字節的查表邏輯一致。最終結果是各個權重字節數據的異或結果。
示例計算數據為 0x AA BB CC DD 11 22 33 44 ,在小端模式是逆序存儲的,所以在計算 CRC 值時是從低字節到高字節(即從右到左)順序計算的。分解計算步驟來分析:
OOMDetector 在查表之前和查表之后都做了一次取反操作 c = ~c,該變體的目的是解決普通 CRC 無法區分只有起始 0 的個數不同的兩個數據。(暫時未理解這個目的,所以直接引用 wiki 中的解釋)
《循環冗餘校驗-wiki》:移位寄存器可以初始化成1而不是0。同樣,在用算法處理之前,消息的最初n個數據位要取反。這是因為未經修改的CRC無法區分只有起始0的個數不同的兩條消息。而經過這樣的取反過程,CRC就可以正確地分辨這些消息了。
- CRC位域多表查表方法
優秀博客
整理編輯:皮拉夫大王在此
本期博客主題:iOS 內存。如果你對以下幾個問題不了解的話,推薦閱讀本期的博客。 - 什么是 MMU?什么是 clean/dirty/compressed memory? - 申請 malloc(1),malloc_size 是多少? - 小內存釋放,內存會立即還給系統嗎? - TCMalloc 主要解決什么問題?
@皮拉夫大王:本文主要介紹了 iOS 內存相關的基礎知識,可以幫助讀者建立內存知識全景圖。我們可以帶著問題去閱讀這篇文章:(1)、虛擬內存是如何映射到物理內存的?(2)、clean/dirty memory是如何區分的?一塊 dirty memory 的單位大小是多少?
@皮拉夫大王:內存分配的硬核文章,內容很有意思。通過閱讀這篇文章,首先我們會了解 free 的過程,順帶也就能理解作者舉的例子:str[0]='a' 報錯非 bad_access 的原因了。另外作者列舉了多種替換系統默認內存分配方式,這也是比較有意思的一點。
@皮拉夫大王:來自微信的 matrix 內存監控原理介紹工具,能夠抓取每個對象生成時的堆棧。與 OOMDetector 的原理一致,但是性能上更勝一籌。如此大量且高頻的堆棧抓取和保存,matrix 是如何做優化的?可以通過閱讀本文來了解細節。
@皮拉夫大王:對《深入理解內存分配》中提到的 TCMalloc 感興趣的可以繼續閱讀這篇文章。
見聞
這一周閱讀/瀏覽到的有趣的資訊。
1、Mac 與游戲無緣,M1 來了也沒用 -- 來自公眾號:APPSO
@遠恒之義:提到游戲,具體到 PC 端的游戲,Mac 電腦基本是沾不上邊的。傳統意義上的 PC 游戲,指的是在 Windows 電腦上玩的游戲,Mac 電腦只是一個生產力工具。我曾下載過戰網客戶端,在 Mac 上玩暴雪游戲《爐石傳說》,但這樣原生支持 Mac 平臺的廠商并不多。我也用過騰訊 START 云游戲,對網絡要求很高,在 MacBook 上玩《英雄聯盟》,打團時的延遲尚能接受。最近拿 PS5 手柄在 iPad 上試玩 Arcade 游戲,游戲體驗還不錯,也能兼容 Mac 平臺。那么,為什么 Mac 距離主流游戲市場這么遠呢?M1 芯片的到來,能給 Mac 游戲帶來新的機遇嗎?作者在文中給出了答案。
2、對 iPod 說再見,我想帶你走進無數人的「青春記憶」 -- 來自少數派:宛潼
@遠恒之義:停產了,售罄了,下架了,擁有 20 年壽命的 iPod,走到了生命的終點。作為一款音樂播放器,iPod 的產品線十分豐富。無論是初代經典 iPod Classic,還是短暫嘗試的 iPod mini,還有被用戶吐槽最多的 iPod shuffle,多次探索新形態、新功能和新技術的 iPod nano,功能強大的 iPod touch,這些都已成為了歷史,讓人懷戀。擁有過 iPod 的你,是否也有「爺青結」的感嘆呢。就讓本文的作者帶你一起了解 iPod 相關的彩蛋產品,喚起你的「青春記憶」吧。
3、Bash tips: Colors and formatting (ANSI/VT100 Control sequences)
@zhangferry:終端常見的輸出樣式是黑白,但實際上它還可以設置顏色和一些簡單的格式,這些樣式的配置可以利用 ANSI 轉義碼。整個過程分為兩步,第一,讓 Bash 識別轉義碼,第二步,指定轉義碼顏色。看一個例子:
bash $ echo -e "\e[31mRed Text\e[0m"
這個命令輸出內容是紅色文本的 Red Text,參數含義說明如下:
| Option | Description | | :----: | :----------------------------------------------------------: | | -e | 開啟反斜杠的轉義功能 | | \e[ | 它是 Bash 識別轉義的起始標志符。\e 是 ASCII 碼中的 ESC,表示控制符,8 進制表示為 \033,也是常見用法。[ 是轉義序列開始標記符 | | 31m | 由 ANSI 轉義碼定義,31 表示紅色,m 表示顏色取值結束 | | \e[0m | \e 含義同上,開始識別 ANSI,0 表示重置設置 |
4、Airport
@zhangferry:TestFlight 是 Apple 用于提供內測功能的應用,一般我們只是用它測試自己的應用或者已安裝應用的升級嘗鮮。TestFlight 版本的 App 有這些優點:審核相比 AppStore 要松很多、功能限制少、對于需要內購的產品可以 0 元嘗鮮。但是對于外界還有哪些不為人熟知的 TF 版應用我們是不清楚的,Airport 要做的事情就是這個,你可以在這里根據分類和搜索挑選你喜歡的應用參與測試。
5、大疆無人機模擬飛行
@zhangferry:這是大疆出的無人機模擬飛行體驗網站,打開之后等待頁面渲染完成就可以在一個虛擬城市里體驗操縱無人機的感覺。該模擬還配備了視角切換、拍照、錄像等物理機具備的所有幾乎所有功能。同時還有物理撞擊的模擬,也就是說如果你飛行中撞到了建筑物,無人機也是會墜毀的,第一視角的墜毀效果做的很不錯。
學習資料
整理編輯:zhangferry
英語進階指南
地址:https://babyyoung.gitbook.io/english-level-up-tips/
英語是程序員繞不過去的一項技能,雖然我們可能從小學就開始接觸英語了,但直到畢業工作,英語能夠不成為學習障礙還是一件不容易的事情。這其中的差別很大成分可以歸結為學習方法,這份文檔就是這樣一個注重方法和可操作性的英語學習指南。
工具推薦
整理編輯:CoderStar
CotEditor
地址:https://coteditor.com/
軟件狀態:免費
軟件介紹:
適用于 macOS 的純文本編輯器,輕巧、整潔并且功能強大。
關于我們
iOS 摸魚周報,主要分享開發過程中遇到的經驗教訓、優質的博客、高質量的學習資料、實用的開發工具等。周報倉庫在這里:https://github.com/zhangferry/iOSWeeklyLearning ,如果你有好的的內容推薦可以通過 issue 的方式進行提交。另外也可以申請成為我們的常駐編輯,一起維護這份周報。另可關注公眾號:iOS成長之路,后臺點擊進群交流,聯系我們,獲取更多內容。
往期推薦
iOS 摸魚周報 #53 | 遠程辦公正在成為趨勢
iOS 摸魚周報 #52 | 如何規劃個人發展
iOS 摸魚周報 #51 | 游戲版號恢復發放
iOS 摸魚周報 第五十期
總結
以上是生活随笔為你收集整理的iOS 摸鱼周报 #54 | Apple 辅助功能持续创新的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Bypass Preventing CS
- 下一篇: 和时间做朋友