使用iOS 8的新特性实现Shutterbug

作者: jack2gs | 来源:发表于2016-07-31 17:29 被阅读0次

    引言

    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选择显示模式:

    1. UIUserInterfaceSizeClassCompact对应UISplitViewControllerDisplayModePrimaryHidden模式
    2. UIUserInterfaceSizeClassRegular对应UISplitViewControllerDisplayModeAllVisible模式
    3. 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的子类充当。程序中我采用的是这种方式。
    1. 何时设置UISplitViewController的委托
      如果你是采用的Storyboard或xib文件,建议在 awakeFromNib 里设置。在查阅资料的时候发现有些人遇到了委托方法没触发的问题。大家都建议尽早的设置委托。

    2. 当在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,它会采用默认的处理方式处理。

    1. 在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里已经过时了。经查阅文档,官方推荐在该方法中处理。

    1. 在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,希望对你有帮助。

    参考资料

    1. UISplitViewControllerUISplitViewControllerDelegate
    2. 2014 WWDC视频Building Adaptive Apps with UIKit
    3. NShipster

    相关文章

      网友评论

        本文标题:使用iOS 8的新特性实现Shutterbug

        本文链接:https://www.haomeiwen.com/subject/edxxsttx.html