你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 使用iOS 8的新特性實現Shutterbug

使用iOS 8的新特性實現Shutterbug

編輯:IOS開發基礎

shutterbug-logo.jpg

引言

Shutterbug是斯坦福大學的Paul Hegarty教授在iOS 7開發教學視頻中給出的一個示例。Shutterbug訪問Flickr的最新圖片列表,並顯示具體的圖片,同時支持iPhone和iPad。具體地參見網易視頻:表格視圖和iPad

視頻中Hegarty教授使用Xcode 6進行代碼演示,為了支持iPhone和iPad同時建立了兩套Storyboard,即Universal App。在看這個視頻的時候,我裝的是Xcode 7。Xcode 7支持在一套Storyboard中創建Universal App,這主要是得益於 Size ClassesAuto Layout 特性,具體的可以看下2014 WWDC視頻Building Adaptive Apps with UIKit。並且從iOS 8後UISplitViewController可以同時在iPhone和iPad中使用。因此,我想用新的特性去實現這個例子。當然,期間遇到了不少問題,走了不少彎路。在此,我將我遇到的問題分享給大家,以避免犯同樣的錯誤。

UISplitViewController和UISplitViewControllerDelegate

官方給出的UISplitViewController的介紹

The UISplitViewController class is a container view controller that presents a master-detail interface. In a master-detail interface, changes in the primary view controller (the master) drive changes in a secondary view controller (the detail). The two view controllers can be arranged so that they are side-by-side, so that only one at a time is visible, or so that one only partially hides the other. In iOS 8 and later, you can use the UISplitViewController class on all iOS devices; in previous versions of iOS, the class is available only on iPad.

它包含兩個視圖控制器,一個是主視圖控制器,另一個是詳細視圖控制器。共有三種顯示模式:

  1. UISplitViewControllerDisplayModePrimaryHidden
    The primary view controller is hidden.

  2. UISplitViewControllerDisplayModeAllVisible
    The primary and secondary view controllers are displayed side-by-side onscreen.

  3. UISplitViewControllerDisplayModePrimaryOverlay
    The primary view controller is layered on top of the secondary view controller, leaving the secondary view controller partially visible.

還有一種叫UISplitViewControllerDisplayModeAutomatic,其實就是讓UISplitViewController根據當前的Size Classes選擇上述的三種顯示模式。真正的顯示模式應該只有三種。

UISplitViewControllerDisplayModeAutomatic 模式下,UISplitViewController會根據水平方向的size class選擇顯示模式:

  • UIUserInterfaceSizeClassCompact對應UISplitViewControllerDisplayModePrimaryHidden模式

  • UIUserInterfaceSizeClassRegular對應UISplitViewControllerDisplayModeAllVisible模式

  • UISplitViewControllerDisplayModePrimaryOverlay對應UISplitViewControllerDisplayModePrimaryHidden模式時以Popover形式顯示主視圖。

具體的可以參考官方文檔或者看下NShipster中的這篇文章。

UISplitViewControllerDelegate的幫助文檔參見蘋果文檔。這裡我介紹下程序中用到的兩個委托方法。

-(BOOL)splitViewController:(UISplitViewController *)splitViewController
collapseSecondaryViewController:(UIViewController *)secondaryViewController
ontoPrimaryViewController:(UIViewController *)primaryViewController
-(void)splitViewController:(UISplitViewController *)svc
willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode

第一個方法當詳細視圖折疊到主視圖時調用,也就是對應的UISplitViewControllerDisplayModePrimaryHidden模式。第二個方法當顯示模式發生變化時調用。下面結合著程序中遇到的問題,介紹下這兩個方法的使用。

遇到的問題及解決方法

1)由誰來充當委托對象
我查了些資料,這個沒有定論,得結合自己的實際情況。

    • Building Adaptive Apps with UIKit這個視頻給出的例子中,由程序委托充當委托。

    • 詳細視圖控制器充當委托。這種情況,我在Stackoverflow上看到的比較多。

    • 通過擴展。NShipster中的這篇文章就是這種方式。

    • 由UISplitViewController的子類充當。程序中我采用的是這種方式。

2)何時設置UISplitViewController的委托
如果你是采用的Storyboard或xib文件,建議在awakeFromNib裡設置。在查閱資料的時候發現有些人遇到了委托方法沒觸發的問題。大家都建議盡早的設置委托。

3)當在iPhone上豎屏顯示時,詳細視圖默認Push到了主視圖之上
解決這個問題可以用以下代碼:

-(BOOL)splitViewController:(UISplitViewController *)splitViewController
collapseSecondaryViewController:(UIViewController *)secondaryViewController
ontoPrimaryViewController:(UIViewController *)primaryViewController
{ if ([secondaryViewController isKindOfClass:[UINavigationController class]]) {     
UINavigationController *nav = (UINavigationController *)secondaryViewController;     
if ([nav.topViewController isKindOfClass:[ImageViewController class]]) {
         ImageViewController *controller = (ImageViewController *)nav.topViewController;         
         if (!controller.imageURL) {             
         return YES;
         }
     }
 } return NO;
}

該方法返回一個BOOL值,如果返回YES表示由我們自己處理,反之交給UISplitViewController,它會采用默認的處理方式處理。

4)在iPad裡,由橫屏切換為豎屏時,詳細視圖左側沒有barButtonItem
解決這個問題可以用以下代碼:

-(void)splitViewController:(UISplitViewController *)svc
willChangeToDisplayMode:(UISplitViewControllerDisplayMode)displayMode
{ UIViewController *primaryViewController = svc.viewControllers[0]; 
UIViewController *secondaryViewController = svc.viewControllers[1]; 
if ([secondaryViewController isKindOfClass:[UINavigationController class]]) {     
UINavigationController *nav = (UINavigationController *)secondaryViewController;     
if ([nav.topViewController isKindOfClass:[ImageViewController class]]) {
         ImageViewController *controller = (ImageViewController *)nav.topViewController;
         controller.navigationItem.leftBarButtonItem=self.displayModeButtonItem;
         controller.navigationItem.leftBarButtonItem.title=((UINavigationController *)primaryViewController).topViewController.title;
         controller.navigationItem.leftItemsSupplementBackButton = true;
     }
 }
}

UISplitViewController沒有給出獲取主和詳細視圖控制器的快捷屬性。在本程序中,viewControllers中的第一個就是主視圖控制器,第二個是詳細視圖控制器,並且與顯示模式無關。
另外,我發現在iOS 7的時代,有幾個其他委托也可以實現這種操作,但是在iOS 8裡已經過時了。經查閱文檔,官方推薦在該方法中處理。

5)在iPad豎屏時,初次進入App,詳細視圖左側沒有barButtonItem
這個問題可以通過初次初始化ImageViewController時設置leftBarButtonItem來解決:

- (void)viewDidLoad {    [super viewDidLoad]; // Do any additional setup after loading the view.    [self.scrollView addSubview:self.imageView];    [self startDownloadingImage];        if(self.traitCollection.userInterfaceIdiom==UIUserInterfaceIdiomPad)    {                self.navigationItem.leftBarButtonItem=self.splitViewController.displayModeButtonItem;    }}

注意:這裡加了個判斷,只有在iPad裡才生效。如果不加判斷,iPhone裡初次顯示詳細視圖時會有問題。

總結

之前很少用到UISplitViewController,發現有些東西剛開始還是有些不易理解。尤其結合著Size Class特性。遇到問題還是應該多看下官方文檔、WWDC相關視頻及Stackoverflow。代碼我已經上傳到Github,希望對你有幫助。

參考資料

UISplitViewController和UISplitViewControllerDelegate

2014 WWDC視頻Building Adaptive Apps with UIKit

NShipster

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved