iOS 9 開發高級技巧
為了慶祝 iOS 9 的正式發布,我們咨詢了一些朋友,讓他們分享一下在適配最新版本 iOS 的過程中所需注意的一些事情。下文列出的就是如何加快速度適配 iOS 9 的絕妙建議。
</div>
Dave Verwer
@daveverwer — Curated創立者,目前正在維護iOS Dev Weekly
</div>很難得的是,iOS SDK 中竟然有個新 API 可以有效幫助應用展示和推銷自己,因此對我來說,iOS 9中最令人激動的新特性就是搜索 API 了。
這些功能是在NSUserActivity的基礎上構建而成的,NSUserActivity在 iOS 8 中為了支持 Handoff 而引進。向應用中加入 iOS 9 提供的額外元數據(metadata)以及深度 URL 連接,便可以讓應用的信息出現在 iOS 9 的 spotlight 搜索隊列當中,不僅可以給用戶展示應用的名稱,還可以讓用戶探索應用中的內容。
這項功能對您現有的用戶帶來的益處是顯而易見的,不僅如此,蘋果還會對這些搜索結果進行排序。當沒有安裝您應用的用戶使用 spotlight 的時候,您的應用同樣也會出現在建議列表當中。這就是所謂的免費營銷?好吧,或許是的。
這項功能最有意思的一點是,蘋果只會給新用戶推薦您的應用;對于老用戶來說,他們將會正常使用您所提供的搜索結果。它將會立即摒棄無用的應用,只顯示那些真正提供實際信息的應用,這對 App Store 來說無疑是一件非常棒的事情。
雖然關于搜索 API 的內容還可大書特書,然而對于“小技巧”來說再說下去無疑是浪費篇幅了。因此,如果您對此項功能感興趣的話,您可以在 WWDC 上觀看Session 709 — Introducing Search APIs。此外,有一個非常好用的工具用來驗證您的網站,以確保 iOS 能夠正常地顯示您的應用鏈接。
</div>
Tim Oliver
@TimOliverAU — iComics創始人
</div>隨著 iPhone 6s 以及 iPhone 6s Plus 的發布,開發者們現在就可以為自己的應用配備上 3D Touch 功能了,從而給界面交互方式開啟一個新的維度。
正如蘋果所言,開發者可以通過非常簡單的 API 來使用 3D Touch ,從根本上來說,也就是UITouch的一個簡單的新屬性。
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) { guard let touch = touches.first else { return } if traitCollection.forceTouchCapability == .Available { println("Touch pressure is \(touch.force), maximum possible force is \(touch.maximumPossibleForce)") } }
這個新的 API 可以讓應用發揮出巨大的潛力,比如說游戲中的額外控制選項、繪圖應用中的細粒度(fine-grained)控制,甚至是用來替代我們在 iOS 設備中使用過的長按操作(tap-and-hold)的極佳選擇。
除了 UITouch 中新增的 API 外,蘋果還為應用提供了兩個用來增加3D Touch 功能的類集:UIPreviewAction和UIApplicationShortcutItem。
UIPreviewAction允許開發者在用戶使用 3D Touch 功能觸控一個 UI 元素的時候,快速地在一個新的預覽窗口中顯示某些內容。這種快速瀏覽應用特定內容的方式真的非常棒,比如說我們可以快速預覽郵件信息、照片,甚至是網頁內容,而無需彈出一個完整的視圖控制器。
UIApplicationShortcutItem對象能夠讓 iOS 主屏幕激活一項令人驚嘆的新特性。當用戶使用 3D Touch 按下某個應用的圖標時,一個選項列表就會被彈出,允許用戶快速跳轉至應用的特定部分,或者執行某項應用內的功能。
總而言之,3D Touch 的引入給 iOS 設備解鎖了一個全新的交互方式,并且將會給接下來的 iOS 應用帶來新一代的創新。關于3D Touch 的實例代碼和相關信息可以在蘋果開發者網站的3D Touch網頁上找到,祝你好運!
Alex Akers
@a2 — 非死book軟件工程師
</div>iOS 9.0 和 OS X 10.11 分別新引進了UILayoutGuide和NSLayoutGuide這兩個類。它們允許您創建一個“類似視圖”的對象,用來參與自動布局約束的計算而無需在屏幕上創建多余的視圖。比如說,您可以使用這些新的類來作為占位圖,而不是創建一個空白的視圖來進行占位。
// 創建Layout Guide let layoutGuideA = UILayoutGuide() let layoutGuideB = UILayoutGuide()// 將它們添加到視圖上 let view: UIView = ... view.addLayoutGuide(layoutGuideA) view.addLayoutGuide(layoutGuideB)
// 使用它們添加約束 layoutGuideA.heightAnchor.constraintEqualToAnchor(layoutGuideB.heightAnchor).active = true
// 您甚至可以設置它們的標識符... layoutGuideA.identifier = "layoutGuideA" layoutGuideB.identifier = "layoutGuideB"
// 然后使用它們可以得到計算后的視圖尺寸(只有當擁有 Layout Guide 的視圖出現之后才有效) print("layoutGuideA.layoutFrame -> (layoutGuideA.layoutFrame)")</pre>
![]()
Indragie Karunaratne
@indragie — Mac、iOS 軟件工程師,學生
</div>在 iOS 9 中引入的NSLayoutAnchorAPI 不僅讓約束聲明更加清晰明了,而且還通過靜態類型檢查以確保您的約束保證能夠正常工作。比如說,我們有一個約束,是使用舊有的NSLayoutConstraintAPI 進行創建的。
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:view1 attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:view2 attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0];
這個約束是無效的,因為我們為 X 軸(左側)屬性以及 Y 軸(頂部)屬性建立了一個相等的約束。然而,這種做法不會得到任何警告,它能夠繼續運行,然后_悄悄_地崩潰掉,讓您的約束處于一個未定義的狀態,接著留下一個棘手的爛攤子讓您來處理,沒有任何的記錄能夠提醒您,以便讓您確認在幾十個(甚至數百、上千)約束中哪一個出現了問題。
NSLayoutAnchor通過使用在 Swift 和 Objective-C 中存在的泛型特性很好地解決了這個問題。UIView上的錨點訪問器(anchor accessors) 能夠顯示為繼承自NSLayoutAnchor方法添加類型信息的NSLayoutAnchor的子類。對于 X 軸、Y 軸以及尺寸(寬、高) 錨點來說,都有著不同的NSLayoutAnchor子類,因為某個類型的錨點只能夠被與之相同類型的其他錨點所約束。通過NSLayoutAnchor中的方法來約束錨點參數以及作為接收器的相同泛型類型,API 變能夠使用類型檢查以確保能夠創建出有效的約束。
讓我們再回到前面的例子來,這里是一個使用NSLayoutAnchorAPI 的等價約束聲明:
NSLayoutConstraint *constraint = [view1.leadingAnchor constraintEqualToAnchor:view2.topAnchor];這不僅比舊有的 API 更加通俗易懂,并且這也會彈出一個“不兼容的指針類型”(Incompatible pointer type)的編譯警告,因為編譯器知道您不能夠創建兩個不同錨點類型的約束。
要了解更多信息,請參閱NSLayoutAnchor documentation。
有關 Swift 和 Objective-C 泛型的注意事項:在寫這篇文章的時候,筆者正使用 Xcode 7 beta 6 版本,Objective-C 的泛型并不能夠很好的與 Swift 建立橋接。這意味著在這個提示中所提及的額外類型安全在 Swift 中并不能使用,但是卻能夠很好地在 Objective-C 中應用,正如Joe Groff所提到的那樣。
![]()
Ayaka Nonaka
@ayanonagon — [Venmo] iOS 工程師(https://venmo.com)
</div>關于 iOS 9 我給出的技巧就是拋棄 iOS 7,開始使用諸如UIAlertController (iOS 8+) 此類的新 API,我喜歡使用這個 API 的原因在于它在顯示警告框、下拉列表以及UIStackView (iOS 9+)的時候會強制只顯示唯一一個視圖控制器,這可以讓我們以一種理智的方式考慮布局。說真的,如果您還沒有試過的話那么我推薦您去試試,它真的非常好用。如果您想要用回原來的 iOS 版本的彈出框,那么您可以使用一些開源庫(PSTAlertController and TZStackView)。因此,一旦您準備拋棄 iOS 7 或者 iOS 8 的時候,那么就使用這個新功能來替換原來的版本吧!
</div>
![]()
Conrad Kramer
@conradev — [Workflow]創立者(https://my.workflow.is/)
</div>蘋果在 iOS 9 中引入了應用傳輸安全功能,它默認需要所有的應用使用 HTTPS 協議。由于不是所有的服務都由 HTTPS 提供,因此蘋果還提供了一個禁用 ATS 的方式,既可選擇性的使用也可全局應用。
如果您的應用需要能夠加載所有的 URL(比如說在 UIWebview中),那么您可能需要通過設置NSAllowsArbitraryLoads鍵值為YES來全局禁用 ATS。這完全是可以的,但是一旦您全局禁用了 ATS 功能,那么您需要在重要區域啟用 ATS 服務。您需要使用NSExceptionDomains鍵來完成此項功能。比如說,這是 Workflow 的 Info.plist 文件的一部分內容:
![]()
您可以看到,我們支持用戶通過 HTTP 下載文件,但是我們同樣也支持通過 HTTPS 來連接 workflow.is(以及所有 Workflow 使用的 API )。
還需要注意的是,每一個包都需要應用 ATS 功能。這意味著您不僅需要給您主應用的 Info.plist 文件添加 ATS 字典,而且還要同時給擴展的 Info.plist 文件添加。
</div>
![]()
Jake Marsh
@jakemarsh — Little Bites of Cocoa創立者
</div>竭盡所能地實現新的搜索功能!竭盡所能地實現新的搜索功能!竭盡所能地實現新的搜索功能!重要的事情說三遍。搜索功能確實是一項重大的進步,iOS 9 僅僅只是個開始。我建議盡快讓您的應用支持NSUserActivity。這個操作是相當地簡單,當您完成之后,您會發現您的應用將同時支持 Handoff 以及 新的系統。如果您的應用還可以有任何形式的搜索內容,那么您一定要 體驗新的 Core Spotlight 框架的優勢并且告訴系統如何對其建立索引。您還應當確保和您應用相關聯的所有網頁內容都針對 iOS 9 的新搜索視圖進行了優化,蘋果對此發布了一個絕佳的指南,指導如何使用一個簡單的meta標簽來完成諸多的功能。
系統對用戶所做所為了解得越多,它所提供給用戶的建議和選項也就更加智能,更加貼合用戶。
</div>
![]()
Sam Ritchie
@FakeSamRitchie — codesplice首席CodeSplicer
</div>每個在共享的 iOS 代碼平臺上工作的人在面對 storyboard 文件合并沖突的時候都會抓狂,這往往導致您不得不在 IB 中手動重制 storyboard 中的更改。這也是許多團隊放棄使用 storyboard 開發并且在source control shingle上提出諸多問題的原因。
如果您沒有任何好用的處理工具的話,那么很不幸,減少合并沖突的最好辦法是將您的 UI 分解成更小的 storyboard 文件。在過去這意味著您需要在代碼中實現導航欄,這樣才能夠跨 storyboard 使用。但是在 Xcode 7 以及 iOS 9 當中,您能夠通過一個名為 Storyboard Reference 的普通 segue 來完成此項功能。它能帶來如同單一 storyboard 導航欄一樣的便利,并且還允許您將文件切割成小份以減少合并沖突。
分離碩大的 storyboard 最快也是最簡單的方法就是將 storyboard 界面放大,然后按下 Shift 鍵選擇要分離并且相關聯的場景,然后選擇菜單欄的 ‘Editor > Refactor to Storyboard’ (沒錯,storyboard 在 Swift 出現之前就支持重構了)即可。然而,這種做法會導致每個被分離的場景仍會在原 storyboard 中留下其引用,并且在必要的時候會自動產生非常難看的 storyboard ID,因此我個人更傾向于使用 ‘File > Duplicate…‘,然后刪除多余的場景即可。
如果您已經擁有了多個 storyboard,那么為自己歡呼一下吧——現在只需要刪除代碼就好了!從對象庫(Object Library)中拖入一個 Storyboard Reference,然后配置一下 segue,接著重重的按下刪除鍵,將導航欄代碼刪除,大功告成!
</div>
![]()
Natasha Murashev
@NatashaTheRobot — Capital One iOS 工程師, Natasha The Robot博主
</div>我并沒有特別關注 iOS 9 的相關內容,不過我倒是在 watchOS 2 上進行的開發工作。如果您擁有一個 Apple Watch 應用的話,那么我建議您應當使用全新的 Watch Connectivity 框架對應用從頭開始進行重寫。WatchOS 2 與原先發布的 WatchKit 擴展完全不同,并且功能更加強大。WatchOS 2 代表著未來,因此仍然維護 WatchKit 擴展無疑只是徒增困擾而已。
此外,如果您目前在 Apple Watch 上使用的是 Notifications、Glances 的話,那么我推薦向您的 Watch 應用中添加 Complication 組件。將來的 #1 (也可能是即將到來的 #1)趨勢正是 Complication,試想當用戶每次抬起手腕之后,您的應用就能夠正好出現,那該是多么美妙的用戶體驗!
要了解更多內容,您可以查看以下資源:
- WWDC 2015 Video: Introducing Watch Connectivity
- WWDC 2015 Video: Creating Complications with ClockKit
- watchOS 2 Tutorials from Kristina Thai
- Getting Data to Your watchOS 2 App
</ul> </div>
![]()
Riley Testut
@rileytestut — GBA4iOS創立者, 就讀于南加利福尼亞大學
</div>如果您和我一樣,讓代碼盡早跳出以便更好地進行邏輯、數據內容的確認,雖然 Swift 自發布的第一天起就讓代碼提早跳出變得可能,但是它仍然還有一些需要注意的地方。首先,您需要檢查不需要的條件(比如說變量為空),而不是檢查您需要的條件。更重要的是,絕大多數情況下,當變量為空的時候,您往往想要讓代碼跳出,然后如果變量不為空的時候就繼續運行,但是接下來如果您想要在剩余的代碼中使用此變量的話,就需要對變量進行手動拆包,。
在 Swift 2當中,Swift 團隊給我們提供了一個完美的關鍵詞:guard來幫助我們提早跳出代碼。guard同時修復了上面提出的兩個問題。試想,您正在玩一個游戲,由于開發者懶得提供不同的回調,因此所有的輸入變化都在一個回調函數中進行處理:
func gameController(gameController: GameControllerType, didActivateInput input: InputType?)在輸入無效的時候使用二次回調似乎更加有效,但是這反而證明了 guard 的極佳用處。如果可選的input是非空值,那么表示某個按鈕被按下了,那么游戲會繼續進行。而如果按鈕不再被按下,那么input就會為空。如果我們只關注于按鈕被按下的情況,我們無需使用如下所示的 Swift 1中所使用的提早退出機制:
func gameController(gameController: GameControllerType, didActivateInput input: InputType?) { if input == nil { return }self.performExampleMethodWithNonOptionalInput(input!)
}</pre>
注意到,我們將輸入和我們不想處理的情況進行了比較,這里是“輸入為空”的情況。更重要的是,當前的輸入值仍然還是一個可選值,因此之后在函數中的使用我們都必須要使用強制解包,即使我們已經 知道它是非空值。在 Swift 2 中,就變得輕松多了:func gameController(gameController: GameControllerType, didActivateInput input: InputType?) { guard let unwrappedInput = input else { return } // 在實際開發中,我往往使用和原變量相同的名字來解包, // 然而,unwrappedInput 這種命名方式要更為清晰一些。 self.performExampleMethodWithNonOptionalInput(unwrappedInput) }
在這里,我們“監視”著input,一旦其為非空值就將其存入到unwrappedInput當中,否則的話就退出方法。現在我們就能夠使用非空值的unwrappedInput了,皆大歡喜!因此,guard 能夠幫助 iOS 9 代碼變得更加清晰易懂,減少錯誤的發生。
![]()
Janie Clayton
@RedQueenCoder — iOS/Mac 開發者, Red Queen Coder博主, NSBrief管理員
</div>我的項目和絕大多數人的有一些小小的不同,我編寫的是 Mac 上的機器人控制程序。面臨 iOS 9、Swift 2以及 El Capitan 的發布,我們已經做好了準備,其中最重要的一點就是 Swift 2 中新出現的錯誤處理(Error Handling)機制了。當 Swift 1發布之后,我們自行編寫了自己的錯誤處理方法,因為在使用 NSError 的時候,我們面臨了許許多多的問題。
由于我們要和硬件打交道,因此錯誤處理對于我們的軟件來說非常重要。因為如果您不能恰當地處理錯誤或者先于錯誤發生前做點什么,那么很有可能會對硬 件造成極大的傷害,這個錯誤的代價就十分地昂貴了!因此,如果要讓我提供關于 iOS 9 的小技巧的話,我想說的是如果您在使用 Swift,那么請盡快掌握錯誤處理。雖然我知道這貨和單元測試一樣,屬于“我們知道應當做,但是它太無趣了而且好像做不做都沒啥關系”一類,但是我建 議,我們并不能控制外界因素所造成的錯誤,因此想想一旦錯誤發生之后,您的應用應當如何應對。
![]()
Glen Low
@pixelglow — Instaviz創始人, Apple Design Award 2004年度獲勝者
</div>為了領悟 UIKit 編程之道,您不應當墨守成規、堅守老舊系統,而是應當追隨 UIKit 框架更新的腳步,不然的話,每當蘋果發布一次新的 iOS 版本,您就會發現蘋果漸行漸遠,而您已無力追隨。
抓住一點:UIKit 的目的在于讓您目前所展示的視圖控制器“切實”地顯示在屏幕上。比如說,對于 Popover 彈出視圖,無論屏幕的尺寸和方向如何,它都能夠重新調整結點位置,自行適應。
開發者可以在 UIAadptivePresentationControllerDelegate 或者 UIPopoverPresentationControllerDelegate 中,獲取系統所適應的顯示默認值以及提供一個新的彈出錨點。在屏幕尺寸或者尺寸級別(Size Class)改變的過程中千萬不要移除您的視圖控制器。此外,這兩個委托只能夠提供一些簡單的自定義功能:當屏幕在自適應的時候,可以很方便地用一個新的 視圖控制器替換掉當前視圖控制器,但是實際改變現有的視圖控制器確實一件相當困難的事情,比如說禁用返回按鈕。
如果不遵守這些約定的話,在旋轉設備、執行 iPad 多任務或者在最新的新功能當中,您的應用輕則會表現出詭異的行為,重則會導致崩潰,從而讓您在漫漫長夜中不得不熬夜苦戰,解決 BUG。
</div>
感謝您的閱讀!現在就行動起來,把這些激動人心的新功能用在您的應用上面吧!
</div> 來自: https://realm.io/cn/news/tips-for-ios-9-development/
本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!相關資訊
sesese色