在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ iOS/ iOS 7 : 隱藏技巧和變通之道
與四軸無人機的通訊
在沙盒中編寫腳本
結(jié)構(gòu)體和值類型
深入理解 CocoaPods
UICollectionView + UIKit 力學(xué)
NSString 與 Unicode
代碼簽名探析
測試
架構(gòu)
第二期-并發(fā)編程
Metal
自定義控件
iOS 中的行為
行為驅(qū)動開發(fā)
Collection View 動畫
截圖測試
MVVM 介紹
使 Mac 應(yīng)用數(shù)據(jù)腳本化
一個完整的 Core Data 應(yīng)用
插件
字符串
為 iOS 建立 Travis CI
先進(jìn)的自動布局工具箱
動畫
為 iOS 7 重新設(shè)計 App
XPC
從 NSURLConnection 到 NSURLSession
Core Data 網(wǎng)絡(luò)應(yīng)用實例
GPU 加速下的圖像處理
自定義 Core Data 遷移
子類
與調(diào)試器共舞 - LLDB 的華爾茲
圖片格式
并發(fā)編程:API 及挑戰(zhàn)
IP,TCP 和 HTTP
動畫解釋
響應(yīng)式 Android 應(yīng)用
初識 TextKit
客戶端
View-Layer 協(xié)作
回到 Mac
Android
Core Image 介紹
自定義 Formatters
Scene Kit
調(diào)試
項目介紹
Swift 的強大之處
測試并發(fā)程序
Android 通知中心
調(diào)試:案例學(xué)習(xí)
從 UIKit 到 AppKit
iOS 7 : 隱藏技巧和變通之道
安全
底層并發(fā) API
消息傳遞機制
更輕量的 View Controllers
用 SQLite 和 FMDB 替代 Core Data
字符串解析
終身學(xué)習(xí)的一代人
視頻
Playground 快速原型制作
Omni 內(nèi)部
同步數(shù)據(jù)
設(shè)計優(yōu)雅的移動游戲
繪制像素到屏幕上
相機與照片
音頻 API 一覽
交互式動畫
常見的后臺實踐
糟糕的測試
避免濫用單例
數(shù)據(jù)模型和模型對象
Core Data
字符串本地化
View Controller 轉(zhuǎn)場
照片框架
響應(yīng)式視圖
Square Register 中的擴張
DTrace
基礎(chǔ)集合類
視頻工具箱和硬件加速
字符串渲染
讓東西變得不那么糟
游戲中的多點互聯(lián)
iCloud 和 Core Data
Views
虛擬音域 - 聲音設(shè)計的藝術(shù)
導(dǎo)航應(yīng)用
線程安全類的設(shè)計
置換測試: Mock, Stub 和其他
Build 工具
KVC 和 KVO
Core Image 和視頻
Android Intents
在 iOS 上捕獲視頻
四軸無人機項目
Mach-O 可執(zhí)行文件
UI 測試
值對象
活動追蹤
依賴注入
Swift
項目管理
整潔的 Table View 代碼
Swift 方法的多面性
為什么今天安全仍然重要
Core Data 概述
Foundation
Swift 的函數(shù)式 API
iOS 7 的多任務(wù)
自定義 Collection View 布局
測試 View Controllers
訪談
收據(jù)驗證
數(shù)據(jù)同步
自定義 ViewController 容器轉(zhuǎn)場
游戲
調(diào)試核對清單
View Controller 容器
學(xué)無止境
XCTest 測試實戰(zhàn)
iOS 7
Layer 中自定義屬性的動畫
第一期-更輕量的 View Controllers
精通 iCloud 文檔存儲
代碼審查的藝術(shù):Dropbox 的故事
GPU 加速下的圖像視覺
Artsy
照片擴展
理解 Scroll Views
使用 VIPER 構(gòu)建 iOS 應(yīng)用
Android 中的 SQLite 數(shù)據(jù)庫支持
Fetch 請求
導(dǎo)入大數(shù)據(jù)集
iOS 開發(fā)者的 Android 第一課
iOS 上的相機捕捉
語言標(biāo)簽
同步案例學(xué)習(xí)
依賴注入和注解,為什么 Java 比你想象的要好
編譯器
基于 OpenCV 的人臉識別
玩轉(zhuǎn)字符串
相機工作原理
Build 過程

iOS 7 : 隱藏技巧和變通之道

當(dāng) iOS 7 剛發(fā)布的時候,全世界的蘋果開發(fā)人員都立馬嘗試著去編譯他們的 app,接著再花上數(shù)月的時間來修復(fù)任何出現(xiàn)的錯誤,甚至從頭開始重建這個 app。這樣的結(jié)果,使得人們根本無暇去探究 iOS 7 所帶來的新思想。除開一些明顯而細(xì)微的更新,比如說 NSArray 的 firstObject 方法——這個方法可追溯到 iOS 4 時代,現(xiàn)在被提為公有 API——還有很多隱藏的技巧等著我們?nèi)ネ诰颉?/p>

平滑淡入淡出動畫

我在這里要討論的并非新的彈性動畫 API 或者 UIDynamics,而是一些更細(xì)微的東西。CALayer 增加了兩個新方法:allowsGroupOpacityallowsEdgeAntialiasing?,F(xiàn)在,組不透明度(group opacity)不再是什么新鮮的東西了。iOS 會多次使用存在于 Info.plist 中的鍵 UIViewGroupOpacity 并可在應(yīng)用程序范圍內(nèi)啟用或禁用它。對于大多數(shù) app 而言,這(譯注:啟用)并非所期望的,因為它會降低整體性能。在 iOS 7 中,用 SDK 7 所鏈接的程序,這項屬性默認(rèn)是啟用的。當(dāng)它被啟用時,一些動畫將會變得不流暢,它也可以在 layer 層上被控制。

一個有趣的細(xì)節(jié),如果 allowsGroupOpacity 啟用的話,_UIBackdropView(被用作 UIToolbar 或者 UIPopoverView 的背景視圖)不能對其模糊進(jìn)行動畫處理,所以當(dāng)你做一個 alpha 轉(zhuǎn)換時,你可能會臨時禁用這項屬性。因為這會降低動畫體驗,你可以回到舊的方式然后在動畫期間臨時啟用 shouldRasterize。別忘了設(shè)置適當(dāng)?shù)?rasterizationScale,否則在 retina 的設(shè)備上這些視圖會成鋸齒狀(pixelerated)。

如果你想要復(fù)制 Safari 顯示所有選項卡時的動畫,那么邊緣抗鋸齒屬性將變得非常有用。

阻塞動畫

有一個小但是非常有用的新方法 [UIView performWithoutAnimation:]。它是一個簡單的封裝,先檢查動畫當(dāng)前是否啟用,如果是則停用動畫,執(zhí)行塊語句,然后重新啟用動畫。一個需要說明的地方是,它并 不會 阻塞基于 CoreAnimation 的動畫。因此,不用急于將你的方法調(diào)用從:

    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    view.frame = CGRectMake(...);
    [CATransaction commit];

替換成:

    [UIView performWithoutAnimation:^{
        view.frame = CGRectMake(...);
    }];

但是,絕大多數(shù)情況下這樣也能工作得很好,只要你不直接跟 CALayer 打交道。

iOS 7 中,我有很多代碼路徑(主要是 UITableViewCells)需要額外保護(hù)以防止意外的動畫,例如,如果一個彈窗(popover)的大小調(diào)整了,與此同時其中的表視圖將因為高度的變化而加載新的 cell。我通常的做法是將整個 layoutSubviews 的代碼包扎到一個動畫塊中:

- (void)layoutSubviews 
{
    // 否則在 iOS 7 的傳統(tǒng)模式下彈窗動畫會滲入我們的單元格
    [UIView performWithoutAnimation:^{
        [super layoutSubviews];
        _renderView.frame = self.bounds;
    }];
}

處理長的表視圖

UITableView 非??焖俑咝В悄汩_始使用 tableView:heightForRowAtIndexPath:,它會開始為你表中 每一個 元素調(diào)用此方法,即便沒有可視對象——這是為了讓其下層的 UIScrollView 能獲取正確的 contentSize。此前有一些變通方法,但都不好用。iOS 7 中,蘋果公司終于承認(rèn)這一問題,并添加了 tableView:estimatedHeightForRowAtIndexPath:,這個方法把絕大部分計算成本推遲到實際滾動的時候。如果你完全不知道一個 cell 的大小,返回 UITableViewAutomaticDimension 就行了。

對于段頭/尾(section headers/footers),現(xiàn)在也有類似的 API 了。

UISearchDisplayController

蘋果的 search controller 使用了新的技巧來簡化移動 search bar 到 navigation bar 的過程。啟用 displaysSearchBarInNavigationBar 就可以了(除非你還在用 scope bar,那你就太不幸了)。我倒是很喜歡這么做,但遺憾的是,iOS 7 上的 UISearchDisplayController 貌似被破壞得相當(dāng)嚴(yán)重,尤其在 iPad 上。蘋果公司看上去像是沒時間處理這個問題,對于顯示的搜索結(jié)果并不會隱藏實際的表視圖。在 iOS 7 之前,這不算問題,但是現(xiàn)在 searchResultsTableView 有一個透明的背景色,使它看上去相當(dāng)糟糕。作為一種變通方法,你可以設(shè)置不透明背景色或者采取一些更富于技巧的手段來獲得你期望的效果。關(guān)于這個控件我碰到過各種各樣的結(jié)果,當(dāng)使用 displaysSearchBarInNavigationBar 時甚至 根本 不會顯示搜索表視圖。

你的結(jié)果可能有所不同,但我依賴于一些手段(severe hacks)來讓 displaysSearchBarInNavigationBar 工作:

- (void)restoreOriginalTableView 
{
    if (PSPDFIsUIKitFlatMode() && self.originalTableView) {
        self.view = self.originalTableView;
    }
}

- (UITableView *)tableView 
{
    return self.originalTableView ?: [super tableView];
}

- (void)searchDisplayController:(UISearchDisplayController *)controller 
  didShowSearchResultsTableView:(UITableView *)tableView 
{
    // HACK: iOS 7 依賴于重度的變通來顯示搜索表視圖
    if (PSPDFIsUIKitFlatMode()) {
        if (!self.originalTableView) self.originalTableView = self.tableView;
        self.view = controller.searchResultsTableView;
        controller.searchResultsTableView.contentInset = UIEdgeInsetsZero; // 移除 64 像素的空白
    }
}

- (void)searchDisplayController:(UISearchDisplayController *)controller 
  didHideSearchResultsTableView:(UITableView *)tableView 
{
    [self restoreOriginalTableView];
}

另外,別忘了在 viewWillDisappear 中調(diào)用 restoreOriginalTableView,否則程序會 crash。 記住這只是一種解決辦法;可能還有不那么激進(jìn)的方法,不用替換視圖本身,但這個問題確實應(yīng)該由蘋果公司來修復(fù)。(TODO: RADAR!)

分頁

UIWebView 現(xiàn)在可以對帶有 paginationMode 的網(wǎng)站進(jìn)行自動分頁。有一大堆與此功能相關(guān)的新屬性:

@property (nonatomic) UIWebPaginationMode paginationMode NS_AVAILABLE_IOS(7_0);
@property (nonatomic) UIWebPaginationBreakingMode paginationBreakingMode NS_AVAILABLE_IOS(7_0);
@property (nonatomic) CGFloat pageLength NS_AVAILABLE_IOS(7_0);
@property (nonatomic) CGFloat gapBetweenPages NS_AVAILABLE_IOS(7_0);
@property (nonatomic, readonly) NSUInteger pageCount NS_AVAILABLE_IOS(7_0);

目前而言,雖然這不一定對大多數(shù)網(wǎng)站都有用,但它肯定是生成簡單的電子書閱讀器或者顯示文本的一種更好的方式。加點樂子的話,請嘗試將它設(shè)置為 UIWebPaginationModeBottomToTop。

會飛的 Popover

想知道為什么你的 popover 瘋了一樣到處亂飛?在 UIPopoverControllerDelegate 協(xié)議中有一個新的代理方法讓你能控制它:

-  (void)popoverController:(UIPopoverController *)popoverController
  willRepositionPopoverToRect:(inout CGRect *)rect 
                       inView:(inout UIView **)view

當(dāng) popover 錨點是指向一個 UIBarButtonItem 時,UIPopoverController 會做出合適的展現(xiàn),但是如果你讓它在一個 view 或者 rect 中顯示,你可能就需要實現(xiàn)此方法并正常返回。一個花費了我相當(dāng)長時間來驗證的問題——如果你通過改變 preferredContentSize 來動態(tài)調(diào)整你的 popover,那么這個方法就尤其需要實現(xiàn)。蘋果公司現(xiàn)在對改變 popover 大小的請求更嚴(yán)格,如果沒有預(yù)留足夠的空間,popover 將會到處移動。

鍵盤支持

蘋果公司不只為我們提供了全新的 framework 用于游戲控制器,它也給了我們這些鍵盤愛好者一些關(guān)注!你會發(fā)現(xiàn)新定義的公用鍵,比如 UIKeyInputEscapeUIKeyInputUpArrow,可以使用全新的 UIKeyCommand 類截查。在 iOS 7 之前,只能通過一些難以言表的手段來處理鍵盤命令,現(xiàn)在,就讓我們操起藍(lán)牙鍵盤試試看我們能用這個做什么!

開始之前,你需要對響應(yīng)鏈(responder chain)有個了解。你的 UIApplication 繼承自 UIResponderUIViewUIViewController 也是如此。如果你曾經(jīng)處理過 UIMenuItem 并且沒有使用我的基于塊的包裝的話,那么你對此已經(jīng)有所了解。事件先被發(fā)送到最上層的響應(yīng)者,然后一級級往下傳遞直到 UIApplication。為了捕獲按鍵命令,你需要告訴系統(tǒng)你關(guān)心哪些按鍵命令(而不是全捕獲)。為了完成這個,你需要重寫 keyCommands 這個新屬性:

- (NSArray *)keyCommands 
{
    return @[[UIKeyCommand keyCommandWithInput:@"f"
                                 modifierFlags:UIKeyModifierCommand  
                                        action:@selector(searchKeyPressed:)]];
}

- (void)searchKeyPressed:(UIKeyCommand *)keyCommand 
{
    // 響應(yīng)事件
}

http://wiki.jikexueyuan.com/project/objc/images/5-14.png" alt="" />

現(xiàn)在可別太激動,需要注意的是,這個方法只在鍵盤可見時有效(比如有類似 UITextView 這樣的對象作為第一響應(yīng)者時)。對于全局熱鍵,你仍然需要用上面提到的 hack 方法。除去那些,這個解決途徑還是很優(yōu)雅的。不要覆蓋類似 cmd-V 這種系統(tǒng)的快捷鍵,它會被自動映射到 paste: 方法。

還有一些新的預(yù)定義的響應(yīng)者行為:

- (void)increaseSize:(id)sender NS_AVAILABLE_IOS(7_0);
- (void)decreaseSize:(id)sender NS_AVAILABLE_IOS(7_0);

它們分別對應(yīng) cmd+ 和 cmd- 命令,用來放大/縮小內(nèi)容。

匹配鍵盤背景

蘋果公司終于公開了 UIInputView,其中提供了一種方式——使用 UIInputViewStyleKeyboard 來匹配鍵盤樣式。這使得你能編寫自定義的鍵盤或者適應(yīng)默認(rèn)樣式的默認(rèn)鍵盤的擴展(工具條)。這個類一開始就存在了,不過現(xiàn)在我們終于可以繞過私有API的方式來使用它了。

如果 UIInputView 是一個 inputView 或者 inputAccessoryView根視圖,它將只顯示一個背景,否則它將是透明的。遺憾的是,這并不能讓你實現(xiàn)一個未填充的分離態(tài)的鍵盤,但它仍然比用一個簡單的 UIToolbar 要好。我還沒看到蘋果在何處使用這個新 API,看上去 Safari 里仍然使用著 UIToolbar

了解你的無線電通信

雖然早在 iOS 4 的時候,大部分的運營商信息已經(jīng)在 CTTelephony 暴露了,但它通常只用于特定場景并非十分有用。iOS 7 中,蘋果公司為其添加了一個方法,其中最有用的:currentRadioAccessTechnology。這個方法能告訴你手機是處于較慢的 GPRS 還是高速的 LTE 或者介于其中。目前還沒有方法得到連接速度(當(dāng)然手機本身也無法獲取這個),但是這足以用來優(yōu)化一個下載管理器,讓其在 EDGE 下不用嘗試 同時 去下載6張圖片了。

現(xiàn)在還沒有 currentRadioAccessTechnology 的相關(guān)文檔,為了讓它工作,會遇到一些麻煩和錯誤。當(dāng)你想要獲取當(dāng)前網(wǎng)絡(luò)信號值,你應(yīng)當(dāng)注冊一個 CTRadioAccessTechnologyDidChangeNotification 通知而不是去輪詢這個屬性。為了確切的使 iOS 發(fā)送這些通知,你需要持有一個 CTTelephonyNetworkInfo 的實例,但不要在通知中創(chuàng)建 CTTelephonyNetworkInfo 的實例,否則會 crash。

在這個簡單的例子中,因為在 block 中捕獲 telephonyInfo 將會持有它,所以我就這么用了:

CTTelephonyNetworkInfo *telephonyInfo = [CTTelephonyNetworkInfo new];
NSLog(@"Current Radio Access Technology: %@", telephonyInfo.currentRadioAccessTechnology);
[NSNotificationCenter.defaultCenter addObserverForName:CTRadioAccessTechnologyDidChangeNotification 
                                                object:nil 
                                                 queue:nil 
                                            usingBlock:^(NSNotification *note) 
{
    NSLog(@"New Radio Access Technology: %@", telephonyInfo.currentRadioAccessTechnology);
}];

當(dāng)手機從 Edge 環(huán)境切換到 3G,日志輸出應(yīng)該像這樣:

iOS7Tests[612:60b] Current Radio Access Technology: CTRadioAccessTechnologyEdge
iOS7Tests[612:1803] New Radio Access Technology: (null)
iOS7Tests[612:1803] New Radio Access Technology: CTRadioAccessTechnologyHSDPA

蘋果導(dǎo)出了所有字符串符號,因此可以很簡單的比較和檢測當(dāng)前的網(wǎng)絡(luò)信息。

Core Foundation,Autorelease 和你

Core Foundation 中出現(xiàn)了一個新的輔助方法,它被用于私有調(diào)用已有數(shù)年時間:

CFTypeRef CFAutorelease(CFTypeRef CF_RELEASES_ARGUMENT arg)

它的確做了你所期望的事,讓人費解的是蘋果花了這么長時間才把它公開。ARC 下,大多數(shù)人在處理返回 Core Foundation 對象時是通過轉(zhuǎn)換成對等的 NS 對象來完成的,如返回一個 NSDictionary,雖然它是一個 CFDictionaryRef,簡單地使用 CFBridgingRelease() 就行了。這樣通常沒問題,除非你返回的沒有可用的對等 NS 對象,如 CFBagRef。你要么使用 id,這樣會失去類型安全性,要么你將你的方法重命名為 createMethod 并考慮所有的內(nèi)存語義,最后使用 CFRelease。還有一些手段,比如這個,使用 non-ARC-file 參數(shù)你才能編譯它,但終歸得使用 CFAutorelease()。另外:不要編寫使用蘋果公司命名空間的代碼,所有這些自定義的 CF-宏將來都會被打破的。

圖片解壓縮

當(dāng)通過 UIImage 展示一張圖片時,在顯示之前需要解壓縮(除非圖片源已經(jīng)像素緩存了)。對于 JPG/PNG 文件這會占用相當(dāng)可觀的時間并會造成卡頓。iOS 6 以前,通常是通過創(chuàng)建一個位圖上下文,然后在其中畫圖來解決。(參見 AFNetworking 如何處理這個問題)。

從 iOS 7 開始,你可以使用 kCGImageSourceShouldCacheImmediately: 強制圖片在創(chuàng)建時直接解壓縮:

+ (UIImage *)decompressedImageWithData:(NSData *)data 
{
    CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
    CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, (__bridge CFDictionaryRef)@{(id)kCGImageSourceShouldCacheImmediately: @YES});

    UIImage *image = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    CFRelease(source);
    return image;
}

剛發(fā)現(xiàn)這一點時我很很興奮,但不要高興得太早。在我的測試中,開啟即時緩存后性能實際上有所 降低。要么這個方法最終是在主線程中被調(diào)用的(好像不太可能),要么感官上的性能下降是因為其在方法 copyImageBlockSetJPEG 中鎖住了,因為這個方法也被用在主線程顯示非加密的圖片時。在我的 app 中,我在主線程中加載小的預(yù)覽圖,在后臺線程中加載大型圖,使用了 kCGImageSourceShouldCacheImmediately 后小小的解壓縮阻塞了主線程,同時在后臺處理大量開銷昂貴的操作。

http://wiki.jikexueyuan.com/project/objc/images/5-15.png" alt="" />

還有更多關(guān)于圖片解壓縮的卻不是 iOS 7 中的新東西,像 kCGImageSourceShouldCache,它用來控制系統(tǒng)自動卸載解壓縮圖片數(shù)據(jù)的能力。確保你將它設(shè)置為 YES,否則所有的工作都將沒有意義。有趣的是,蘋果在 64-bit 運行時的系統(tǒng)中將 kCGImageSourceShouldCache默認(rèn)值 從 NO 改為了 YES。

盜版檢查

蘋果添加了一個方式,通過 NSBunble 上的新方法 appStoreReceiptURL 來獲取和驗證 Lion 系統(tǒng)上 App Store 的收據(jù),現(xiàn)在終于也移植到了 iOS 上了。這使得你可以檢查你的應(yīng)用是合法購買的還是被破解了的。檢查收據(jù)還有另一個重要的原因,它包含了 初始購買日期,這點對于把你的應(yīng)用從付費模式遷移到免費+應(yīng)用內(nèi)付費模式很有幫助。你可以根據(jù)這個初始購買日期來決定額外內(nèi)容對于你的用戶是免費(因為他們已經(jīng)付過費了)還是收費的。

收據(jù)還允許你檢查應(yīng)用程序是否通過批量購買計劃購買以及該許可證是否仍有效,有一個名為 SKReceiptPropertyIsVolumePurchase 的屬性標(biāo)示了該值。

當(dāng)你調(diào)用 appStoreReceiptURL 時,你需要特別注意,因為在 iOS 6 上,它還是一個私有 API,你應(yīng)該在用戶代碼中先調(diào)用 doesNotRecognizeSelector:,在調(diào)用前檢查運行(基礎(chǔ))版本。在開發(fā)期間,這個方法返回的 URL 不會指向一個文件。你可能需要使用 StoreKit 的 SKReceiptRefreshRequest,這也是 iOS 7 中的新東西,用它來下載證書。使用一個至少有過一次購買的測試用戶,否則它將沒法工作:

// 刷新收據(jù)
SKReceiptRefreshRequest *request = [[SKReceiptRefreshRequest alloc] init];
[request setDelegate:self];
[request start];

驗證收據(jù)需要大量的代碼。你需要使用 OpenSSL 和內(nèi)嵌的蘋果根證書,并且你還要了解一些基本的東西像是證書、PCKS 容器以及 ASN.1。這里有一些樣例代碼,但是你不應(yīng)該讓它這么簡單——尤其是對那些有“高尚意圖”的人,別只是拷貝現(xiàn)有的驗證方法,至少做點修改或者編寫你自己的,你應(yīng)該不希望一個普通的補丁程序就能在數(shù)秒內(nèi)瓦解你的努力吧。

你絕對應(yīng)該讀讀蘋果的指南——驗證 Mac App 商店收據(jù),這里面的大多數(shù)都適用于 iOS。蘋果在 WWDC 2013 的 Session 308 “Using Receipts to Protect Your Digital Sales” 中詳述了通過新加入的“Grand Unified Receipt”而帶來的變動。

Comic Sans MS

承認(rèn)吧,你是懷念 Comic Sans MS 的。在 iOS 7 中,Comic Sans MS 終于回來了。iOS 6 中添加了可下載字體,但那時的字體列表很少也不見得有趣。在 iOS 7 中蘋果添加了不少字體,包括 “famous”,它和 PT SansComic Sans MS 有些類似。kCTFontDownloadableAttribute 并沒有在 iOS 6 中聲明,所以 iOS 7 之前它并不真正可用,但蘋果確是在 iOS 6 的時候就已經(jīng)做了私有聲明了。

http://wiki.jikexueyuan.com/project/objc/images/5-16.png" alt="" />

字體列表是動態(tài)變化的,以后可能就會發(fā)生變動。蘋果在 Tech Note HT5484 中羅列了一些可用的字體,但這個文檔已經(jīng)過時了,并不能反映 iOS 7 的變化。

這里顯示了你該如何獲取一個用 CTFontDescriptorRef 標(biāo)示的可下載的字體數(shù)組:

CFDictionary *descriptorOptions = @{(id)kCTFontDownloadableAttribute : @YES};
CTFontDescriptorRef descriptor = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)descriptorOptions);
CFArrayRef fontDescriptors = CTFontDescriptorCreateMatchingFontDescriptors(descriptor, NULL);

系統(tǒng)不會檢查字體是否已存在于磁盤上而將直接返回同樣的列表。另外,這個方法可能會啟用網(wǎng)絡(luò)并造成阻塞,你不應(yīng)該在主線程中使用它。

使用如下基于塊的 API 來下載字體:

bool CTFontDescriptorMatchFontDescriptorsWithProgressHandler(
         CFArrayRef                          descriptors,
         CFSetRef                            mandatoryAttributes,
         CTFontDescriptorProgressHandler     progressBlock)

這個方法能操作網(wǎng)絡(luò)并傳遞下載進(jìn)度信息來調(diào)用你的 progressBlock 方法直到下載成功或者失敗。參考蘋果的 DownloadFont 樣例看看如何使用它。

有一些值得注意的地方,這里的字體只在當(dāng)前程序運行時有效,下次運行將被重新載入內(nèi)存。因為字體存放在共享空間中,你不能依賴于它們是否可用。很有可能但不能保證地說,系統(tǒng)會清理這個目錄,或者你的程序被拷貝到?jīng)]有這個字體的新設(shè)備中,同時你又沒有網(wǎng)絡(luò)。在 Mac 或是模擬器上,你能根據(jù) kCTFontURLAttribute 獲得字體的絕對路徑,加載速度也會提升,但是在 iOS 上是不行的,因為這個目錄在你的程序之外,你需要再次調(diào)用 CTFontDescriptorMatchFontDescriptorsWithProgressHandler。

你也可以注冊新的 kCTFontManagerRegisteredFontsChangedNotification 通知來跟蹤新字體在何時被載入到了字體注冊表中。你可以在 WWDC 2013 的 Session 223 “Using Fonts with TextKit”中查找更多信息。

這還不夠?

沒關(guān)系,iOS 7 的新東西遠(yuǎn)不止如此!了解一下 NSHipster 你將明白語音合成相關(guān)的東西,base64、全新的 NSURLComponents、NSProgress、條形碼掃描、閱讀列表以及 CIDetectorEyeBlink。還有很多我們沒有涵蓋到的,比如蘋果的 iOS 7 API 變化,指南以及 Foundation Release Notes(這些都是基于 OS X的,但是代碼都是共享的,很多也同樣適用于 iOS)。很多新方法都還沒形成文檔,等著你來探究和寫成博客。