(原文:raywenderlich 作者:Jack Wu 譯者:@TurtleFromMars)
過節啦!為慶祝佳節,看看我給這篇文章寫的這段極客小詩吧:
“Keynote前夜,無人知曉,新API能否登場
對Siri的期待,Touch ID的希望
而此刻iOS 8應聲而出,震驚全場
擴展,Swift,Metal,整整一籮筐
通用Storyboard,又有誰曾料想
一片歡呼聲中,有人開始迷惘
現有的這些App,適配問題實在惆怅
不過不必擔心,因為這篇教程會與您講講
新的API和屏幕尺寸,助你的App煥發容光
遵循十條小貼士,豁然開朗
iOS 8萌萌哒!嗯……老鴨粉絲湯?”
先不管詩寫的怎樣,言歸正傳——讓你的App適配iOS 8和新設備的十條小貼士——正好趕上節假日!:]
你可能會想 “我在iPhone 6 Plus上把我的App遛了一遍,看起來沒啥問題” 。沒錯,你的App跑起來應該和原來一樣,但這並不意味著你可以就此收手!
讓現有的App在 放大顯示模式(Scale Mode) 下運行,這一點Apple已經做得不錯了,App單純地被放大,以此適應更大的屏幕。隨便掃一眼,似乎還可以,但你會發現上面的狀態欄也變大了。現在你一定想讓自己的App在全屏顯示模式下運行吧,有圖有真相:
全屏顯示模式讓你的App能在相同的屏幕空間內顯示更多的信息。注意,狀態欄的大小也不一樣。在這張圖片中,文字可能看起來特別小,但在Retina HD屏幕上看起來剛好合適。
現在開始准備適配全屏顯示模式,那麼問題來了: 要放棄支持iOS 7嗎?
你總要做出最終抉擇,然而這裡還有幾點值得考慮:
iOS 7用戶依然能在App Store上獲取當前版本。
大屏設備(iPhone 6和iPhone 6 Plus)運行系統的最低版本是iOS 8。
雖然iOS 8的采用率低於一年前同期的iOS 7,但也已經超過60%。
酷炫的新API。:]
好,現在你心意已決,接下來我們分三個小節來講 讓你的App適配iPhone 6,iPhone 6 Plus和iOS 8的十條小貼士。
注:如果你選擇iOS 7為更新的目標系統,你依然可以使用新API。欲知如何在同一個App中支持不同的iOS版本和設備,請參閱 支持不同的iOS版本和設備 。
如果你的App已經在用Storyboard和Auto Layout,那就省事了,適配工作輕而易舉。如果沒有, 更待何時? Size Class 依賴於 Auto Layout 和 通用Storyboard(Universal Storyboard),顯然Apple已經清楚表明Storyboard會是將來iOS App的一大中心。
而且,沒有這個的話最新的SDK WatchKit根本跑不起來。
好消息是,如果你還沒選用,raywenderlich.com上有幾篇關於Storyboard和Auto Layout的優秀教程。我很中意這幾篇:
Swift語言Storyboard教程 第1部分
Swift語言Storyboard教程 第2部分
Swift語言Auto Layout入門教程 第1部分
Swift語言Auto Layout入門教程 第2部分
要開始實現自適應布局,第一步就是把現有的Storyboard轉換成 通用Storyboard ——一個可以處理任何屏幕大小界面的Storyboard。
你要做的只是點擊一下!打開你的Storyboard,在Info Panel(command+option+1)信息面板中選定 Use Size Classes :
你會注意到你的視圖都變成了正方形。先別太激動,這並不意味著你的App現在可以支持黑莓Passport手機,這只是一個適配 Any(任意) 屏幕尺寸的代表性尺寸。
所有的約束應該是原樣保留了下來,目前還沒有任何實質變化。你可以使用 Assistant Editor(輔助編輯器) 中新加的 Preview(預覽) 模式來確認這一點。
你現在 可以 做的是為不同的尺寸類別單獨設置約束。要深入學習自適應布局,尺寸歸類和通用Storyboard,請參閱自適應布局入門。
注:如果你的App是Universal App,你可能為iPhone和iPad界面單獨准備了不同的Storyboard。這裡有兩種選擇:
繼續使用分開的Storyboard。只把iPhone的Storyboard,或把所有的Storyboard轉換成通用Storyboard,然後依然分別為iPhone和iPad進行適配。
砍掉重練!改成一個通用Storyboard!這樣以後就只需維護一個Storyboard,不過這個方案的工作量可不小。目前Xcode中還沒有幫助你重構的工具,轉換只能靠自己。
回想一下,全屏顯示模式比放大顯示模式爽多了,而你剛剛完成的工作只是采用自適應布局,如果你的App不能在全屏顯示模式下運行的話,這又有何益呢?幸運的是,開啟全屏顯示模式相當容易,還有一點額外的好處!
Apple如是說:
在運行時,系統會查找Storyboard launch screen file(Storyboard啟動畫面文件),如果想讓系統知道你的App支持iPhone 6的不同屏幕尺寸,請在你的App Bundle裡包含一個Storyboard啟動畫面文件。 如果存在這樣的文件,系統會認定你的App明確適配iPhone 6和iPhone 6 Plus並在全屏顯示模式下運行。
打住! 啟動畫面Storyboard ?也許你會問:“顧名思義的話……我再也不用准備20個啟動畫面圖片了?”
對對對!確定一定以及肯定!
這就開工吧,由 New File 向你的App中添加一個新文件。在iOS > User Interface當中有一個新的文件類型 Launch Screen ,名副其實,向你的App添加一個新的啟動畫面!話說Xcode創建的默認啟動畫面真是有點寒碜。
有意思,前面我們聊的都是Storyboard,這下Xcode為你創建了一個 xib 文件。趕緊打開這個xib,刪掉那幾個丑到爆的label,把它裝扮成你喜歡的樣子吧。如果想讓它和以前一樣的話,只要添加一個包含啟動圖片的UIImageView
就可以了。
最後,到項目綜合設置(General Settings)裡像這樣選擇你的新xib文件為 Launch Screen File :
構建你的App並在iPhone 6 Plus模擬器上運行,新啟動畫面和超贊的全屏顯示模式,盡情享受吧。
注:如果要支持iOS 7和/或更老的系統版本,你依然要提供4英寸啟動圖片。否則你的App會以3.5英寸模式顯示。
iPhone 6 Plus配備了401 PPI的新一代 Retina HD 顯示屏 。要適配這麼高的分辨率,你需要提供 3倍 分辨率的圖片。就像@2x圖片一樣,你要做的就是提供@3x圖片,iOS會幫你加載正確的圖片。
注:iPhone 6同樣配備了Retina HD 顯示屏,但其像素密度與前代Retina iPhone相同,依然加載@2x的圖片資源。
你的App可以在全屏顯示模式下運行了!喜大普奔!
不過還有很多問題要處理,請先不要離開!
用戶一定會喜歡iOS 8在隱私設置方面的改進。
不幸的是,如果使用不當,你的App可能會崩潰。
在這一小節中,你將修復這些問題,讓用戶放心、開心。
往下看,這小節的三條小貼士:
iOS 8引入請求用戶位置的兩個新權限:一個僅當App運行時接收更新,另一個可以在App未運行的時候接收更新。
以前,開始監視位置的時候,iOS會自動向用戶尋求App權限。這一點在iOS 8中有所改變,你需要在開始更新位置之前明確地顯式請求用戶許可。
為此,如果當前許可狀態不明,你需要調用 CLLocationManager 的requestWhenInUseAuthorization
或requestAlwaysAuthorization
方法。
在CLLocationManager調用startUpdatingLocation
方法之前加上這個調用就行了。就這麼簡單:
self.locationManager = [[CLLocationManager alloc] init]; self.locationManager.delegate = self; if ([CLLocationManager authorizationStatus] == kCLAuthorizationStatusNotDetermined) { [self.locationManager requestWhenInUseAuthorization]; } [self.locationManager startUpdatingLocation];
最後一步:在App的 info.plist 中添加 NSLocationWhenInUseUsageDescription 或 NSLocationAlwaysUsageDescription 為新鍵,然後輸入告知用戶請求許可的字符串。例如:“顯示附近的物品項需要獲取您的位置。”
在iOS 8中,用戶通知許可有變動,主要是為了支持 可操作通知 。老版本的相關API在iOS 8中無效,不宜使用。
現在,通知許可共分為兩 層 ,你的App必須先請求許可 顯示 特定類型的通知,而成功得到用戶許可後,你需要請求許可接收 遠程 通知。
之前的做法是在-application:didFinishLaunchingWithOptions:
內調用-registerForRemoteNotificationTypes:
來接收delegate回調檢查狀態。如果在iOS 8中這麼寫,你會發現根本沒有調用delegate方法。
這是由於你需要先請求第一層用戶通知許可。以下是 appDelegate 中的一個簡單示例:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 1 UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]; // 2 [application registerUserNotificationSettings:settings]; return YES } - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { // 3 if (notificationSettings.types != UIUserNotificationTypeNone) { // 4 [application registerForRemoteNotifications]; } } // 5 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { // ... (no changes needed) } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { // ... (no changes needed) }
與之前相比多了一個回調,下面是這幾步的簡要解釋:
首先創建一個UIUserNotificationSettings
,一個定義了App顯示通知類型的設置對象,其中也包括定義操作的類目(categories)。
調用-registerUserNotificationSettings:
,傳入設置對象。這會向用戶請求許可。
當用戶給予回應,新的delegate方法-application:didRegisterUserNotificationSettings:
被調用。這裡傳入的notificationSettings
與第二步傳入的那個對象不一定相同。這個只描述得到了用戶許可的權限。查看types
就可以驗證用戶許可了那些權限。
如果成功獲得用戶許可,現在可以調用-registerForRemoteNotifications
。注意這個方法不再接受參數了。現在設置信息已經被設置對象捕獲,這裡只要請求接受遠程通知。
此後依然能像往常一樣通過相同的回調來獲取設備令牌(device token)。
如果用戶在詢問首次出現時拒絕許可,那麼以後就不再彈出詢問。如果用戶拒絕了一個必要的許可,常見的情形是在App中顯示錯誤頁面,或是告訴用戶如何到 設置隱私 中開啟相應許可的提示。上述做法多少顯得有些笨拙,也有不少App因此得到了差評。
iOS 8提供 UIApplicationOpenSettingsURLString 來簡化這部分工作。這個字符串常量的特性是:把它傳入-openURL:
方法會直接讓用戶跳轉到相應App的設置。這樣一來,請求許可省了不少事。
正確的使用姿勢是在一個按鈕或提示的操作(Action)中加入這行代碼:
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
現在你的App已經完成iOS 8適配,可喜可賀,iOS 8的新API正等著你呢。
特性適配終於大功告成,App完全可以正常工作了,現在開始享受樂趣吧 :]
使用Swift語言最明顯的好處就是縮減文件數和代碼行數。不必用Swift重寫任何現有代碼,甚至在現有項目中你都可以直接在新類和新文件中開始寫Swift代碼。
以下是確保Swift和Objective-C在項目中和平共處的參考建議:
在項目中首次添加Swift文件時,Xcode會為你創建 橋接頭文件(bridging header) 。請允許Xcode如此處理。
如果想在Swift文件中使用Objective-C類,請用一條標准#import
語句將Objective-C頭文件導入橋接頭文件。
如果想在Objective-C代碼中使用Swift類,請將包羅頭文件(umbrella header)ProductModuleName-Swift.h
導入相應的.m
文件,其中 ProductModuleName 是模塊名,多數情況下是項目名稱,但還是去項目設置裡仔細檢查一下比較好。
確保你的Swift類要麼繼承一個Objective-C類(例如NSObject
),要麼使用@objc
注明類名和方法名。
要深入了解Swift,請參閱我們的Swift教程還有iOS教程書目,其中多數教程已經為Swift更新或談及Swift。
如果想深入學習如何協同使用Swift和Objective-C,請參閱Apple的與Cocoa和Objective-C協同使用Swift指南。
iOS 8更新了Cocoa Touch的一些基本成分。UIAlertView
,UIActionSheet
還有UISearchDisplayController
都有了用起來更順心的替代品,而UIPresentationController
在視圖控制器的呈現過程中會發揮大家喜聞樂見的作用。
UIAlertController 取代了UIAlertView
和UIActionSheet
,提供基於block回調的優雅接口。舉個例子:
UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Are you sure?" message:@"Once deleted this item cannot be recovered." preferredStyle:UIAlertControllerStyleAlert]; [alert addAction: [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { [self deleteItem ]}]; [alert addAction: [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:{}]; [self presentViewController:alert animated:YES completion:nil];
如你所見,再也不用指定delegate了,想呈現就調用-presentViewController:
,看著多舒服, 就是這個味兒。UIAlertController
也帶來了一些新功能,比如多按鈕還有文本框的簡單配置。
想了解更多,請參閱 NSHipster 上的這篇精品文章:UIAlertController (中譯版)。
UIPresentationController 讓你在呈現視圖控制器時隨心所欲。以優雅的、可重用的方式來隨意操控呈現的色調、位置和動畫效果。
要深入了解呈現控制器(Presentation controller),請參閱官方文檔或iOS 8教程的第六章“呈現控制器簡介”。
模糊效果是iOS 7廣受喜愛的新特性之一。Apple終於在iOS 8中公開了這個API:全新的 UIVisualEffectView 和 UIVibrancyEffectView 類!
UIVisualEffectView 是一種弱化背景的有效方式,而 UIVibrancyEffectView 會讓前景更加艷麗。這兩個類都已經做過優化,但濫用的話,它們會拖慢你的App性能,一定要謹慎使用。
想入門iOS 8視覺效果的話,請看我們的 iOS 8視覺效果教程。
本教程的主要內容是如何讓你的App在iOS 8上運行,按著前面的這些小貼士來,干得漂亮!好(壞?)消息是這 還 只是剛開始,iOS 8帶來的東西太多啦!
在iOS 8中擴展App功能的方法很多,把以前的不可能化為可能。以下是為你的App錦上添花的幾點參考:
利用 WatchKit 為你的App創建手表擴展。
創建 Today Extension ,讓用戶在通知中心關注信息。
利用 Document Provider 實現應用間的文件共享。
在通知中添加 Action 操作。
集成 Touch ID 方便用戶進行身份認證。
要深入了解關於iOS 8和WatchKit的更多內容,請參閱 iOS 8教程 還有 WatchKit教程。
iOS 8前所未有地為更多功能敞開了大門。
帶著這些新工具,似乎再次迎來了一個新的開端。
希望您喜歡這篇文章,從這些小貼士中獲益。
朋友們,繼續前進,用代碼創造歡聲笑語! :]
本篇教程內容紛纭雜沓,但願我表達足夠清晰。
以下鏈接供讀者參考:
支持不同的iOS版本和設備
Storyboard教程
Auto Layout教程
我們的Swift教程集
我們的iOS 8教程集
與Cocoa和Objective-C協同使用Swift
NSHipster上的UIAlertController
UIPresentationController官方文檔
iOS 8視覺效果
iOS 8教程
WatchKit教程
Swift教程集
(本文為CocoaChina組織翻譯,本譯文權利歸譯者所有,未經允許禁止轉載。)