由于iOS內(nèi)置的字體無法完全滿足設(shè)計的需求,所以有時需要使用非內(nèi)置的字體呢撞,這時候就需要注冊字體庫了损姜。iOS提供了兩種注冊字體庫的方式,最常用的一種方式可以稱之為靜態(tài)注冊殊霞,另外還有動態(tài)注冊的方式摧阅。
靜態(tài)注冊
所謂靜態(tài)注冊的方式就是把字體庫打包到App內(nèi)部,在App啟動的時候由系統(tǒng)完成字體的注冊绷蹲,程序不需要主動處理棒卷,App完成啟動后就可以直接使用注冊的字體。這種方式的詳細使用可以參考蘋果官方文檔Adding a Custom Font to Your App
簡單的來說這種注冊方式只需要兩步:
- 加入需要注冊的字體庫文件
-
在工程的Info.plist中新增一個Key:“Fonts provided by application”祝钢,把字體庫文件名增加到Value中
如下圖所示:
這種注冊方式步驟簡單比规,特別適用于App啟動后就需要使用自定義字體的場景,但是這種方式會導(dǎo)致安裝包增大拦英,特別是中文字體庫相對來說是比較大的蜒什。
動態(tài)注冊
最初,因為我們的App在啟動后就需要用到注冊的字體疤估,所以也是使用靜態(tài)注冊字體的方式灾常。后來我們集成了Flutter,而Flutter中也用到了這些字體铃拇,調(diào)研發(fā)現(xiàn)Flutter是無法直接訪問到App中內(nèi)置的字體庫的钞瀑,因此就導(dǎo)致了這些字體庫在Native中內(nèi)置了一份,在Flutter中也內(nèi)置了一份锚贱,安裝包增加了好多仔戈,影響了用戶體驗。
為了減少安裝包大小拧廊,我們將Native中的字體更改為動態(tài)注冊监徘,具體方法就是在App啟動的時候加入了動態(tài)注冊字體的代碼,核心代碼如下:
guard let fontData = NSData.init(contentsOfFile: "path/for/font/file") else {
return
}
let fontBytes = fontData.bytes.assumingMemoryBound(to: UInt8.self)
guard let fontDataPtr = CFDataCreate(kCFAllocatorDefault, fontBytes, fontData.length),
let provider = CGDataProvider.init(data: fontDataPtr),
let font = CGFont.init(provider) else {
return
}
var error: Unmanaged<CFError>?
if !CTFontManagerRegisterGraphicsFont(font, &error) {
// let errorDescription = CFErrorCopyDescription(error as! CFError)
print("Register Error")
}
else {
print("Register Success")
}
使用動態(tài)注冊的方式完美的解決了我們遇到的問題吧碾,帶來了10多M包體積的縮小凰盔。
但是在使用iOS10的設(shè)備測試的時候發(fā)現(xiàn)App在啟動頁就直接崩潰了,經(jīng)過調(diào)試發(fā)現(xiàn)崩潰在let font = CGFont.init(provider)
倦春,在stackoverflow上找到了答案:CGFontCreateWithDataProvider hangs in airplane mode