[iOS UI] 显示

作者: 段子周 | 来源:发表于2015-09-06 17:57 被阅读2638次

    概述

    在所有拥有UI的系统开发工作中,一般开发人员最先认识的都是UI系统,这也是在自然界人们认知事物的习惯-从表及里的认知过程。

    从我个人的经验出发,包括iOS,Android,Qt等完成一个App UI开发,总结来都可以从下图3个部分来完成,那么要系统地掌握一个系统UI开发过程和其中的问题,都可以从这3个方面来认知和展开。

    程序UI完成步骤

    这篇文章,主要探讨一下第一部分- view显示

    问题和结论

    view显示
    如图 view显示,关于这个主题我们需要搞清楚两件事情(并给出结论):
    1. iOS界面显示到底是什么在显示?

    UIView的层级结构显示

    1. 具体是通过什么方式显示
    • 通过UIViewController进行UIView管理并显示
    • 通过代码
    • nib file
    • storyboard
    • 直接对UIWindow进行addSubView的操作(实际开发中不这么做)

    解析

    问题1

    我们首先看看显示一个简单的“hello view”需要做哪些工作。在Xcode中创建一个Single View Application,打开Main.storyboard,在右下角的Object Library中拖一个Label到Main.storyboard的画布中(靠近左上角放置),修改Label的文字“hello view”,运行,就会看到我们想要的界面。
    程序在模拟器中运行起来之后,在Xcode中选择Debug View Hierarchy,回看到如下图的app view 3d渲染: 我们可以看到实际上组成界面的是UIWindow->UIView->UILabel

    view hierarchy.png

    因为iOS是通过UIScreen类拿到硬件屏幕显示,所以事实上,UIWindow是添加到UIScreen上以最终显示,所以完整的结构是下图所示(撒懒网上找得图哈)

    网图

    问题2

    window.addSubView

    验证问题1所展示的例子,是使用storyboard完成的,在代码层具体做了些什么,Interface Builder替我们完成了。这一节我们来探究代码实现。
    新建一个Single View Application,打开AppDelegate.swift(OC相应代码很容易参照完成),修改第一个方法如下代码示例1:

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Override point for customization after application launch.
            
            window = UIWindow(frame: UIScreen.mainScreen().bounds)
            var text = UILabel(frame: CGRectMake(20, 20, 100, 50))
            text.backgroundColor = UIColor.greenColor()
            text.text = "Hello World"
            window?.addSubview(text)
            window?.makeKeyAndVisible()
            
            return true
        }
    

    运行,结果如下图:


    addSubView.png

    可以看到,同样达到了显示一个UILabel到屏幕上的结果,我们可以删除Main.storyboard以证明是我们的代码得到了这样的结果(当然这不是必要的)。
    查看注释非常容易理解上面程序做得事:

    创建一个UIWindow占满整个UIScreen,然后创建了一个UILabel,把它加到UIWindow,最后把UIWindow设置为主Window并显示。

    通过ViewController

    通过代码

    虽然这样能把UIView显示在屏幕上,并且也可以构建复杂的View hierarchy,但是这是Apple不推荐的,整个iOS开发推荐的管理界面的方法是使用ViewController。
    咱们对上面的代码进行修改,把整个方法修改为如下代码示例2:

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Override point for customization after application launch.
            
            window = UIWindow(frame: UIScreen.mainScreen().bounds)
            var text = UILabel(frame: CGRectMake(20, 20, 100, 50))
            text.backgroundColor = UIColor.greenColor()
            text.text = "Hello World"
            var vc = UIViewController()
            vc.view.addSubview(text)
            window?.rootViewController = vc
            window?.makeKeyAndVisible()
            
            return true
        }
    

    运行程序,得到和addSubView.png一样的效果

    主要的改动就是引入了UIViewController并把ViewController设置为window.rootViewController,而本来直接加入window子view的UILabel,被UIViewController的View管理起来

    在现实开发中,ViewController要控制View显示的方方面面,加载,修改,布局等等,所以,代码示例2在这里创建UIViewController并进行View的组装仅仅是为了易于理解,真正的开发中,代码实现界面显示会是如下的做法:
    下图是Xcode Single View Application默认的工程结构,


    default project structure.png

    打开ViewController.swift,覆盖loadView()方法,修改完的代码示例如下:

    import UIKit
    
    class ViewController: UIViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        override func loadView() {
            
            let v = UIView()
            self.view = v
            
            let label = UILabel(frame: CGRectMake(20, 20, 100, 50))
            label.backgroundColor = UIColor.greenColor()
            label.text = "hello world"
            v.addSubview(label)
        }
    }
    

    然后我们得修改AppDelegate的第一个方法如下代码示例:

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Override point for customization after application launch.
            
            window = UIWindow(frame: UIScreen.mainScreen().bounds)
            window?.rootViewController = ViewController()
            window?.makeKeyAndVisible()
            
            return true
        }
    

    运行程序,还是会得到addSubView.png一样的效果

    除了代码创建UI外,iOS还提供了两种方式来所见即所得地创建UI,storyboard和nib file,两者其实都是本地化存储的iOS对象,在运行时加载组装和代码一起完成UI的构建和显示,现在storyboard是Xcode默认方式,我们从它看起。

    storyboard

    新建一个Single View Application,给storyboard中加入一个UILabel “hello world",然后修改AppDelegate.swift第一个方法如下代码示例:

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Override point for customization after application launch.
            
            window = UIWindow(frame: UIScreen.mainScreen().bounds)
            var mainSb = UIStoryboard(name: "Main", bundle: nil)
            window?.rootViewController = mainSb.instantiateInitialViewController() as? UIViewController
            window?.makeKeyAndVisible()
            
            return true
        }
    

    运行工程,会得到跟没有修改AppDelegate.swift之前一样的结果。其实,这就是默认Single View Application隐性为我们做得事:

    加载storyboard,从storyboard中加载initial View Controller,并把initial View Controller设置为window的rootViewController

    nib file

    新建一个Single View Application,新建一个User Interface -> View, 命名MainNib,创建完成会生成一个MainNib.xib。选中MainNib.xib,点击View上面的File’s Owner,然后在右侧Identity Inspector中Custom Class的Class框里填上工程生成的ViewController。再选择最右边的Connection Inspector,将Outlets下面的View拖向画布(也就是UIView),将ViewController的View和MainNib.xib中的View进行连接。拖一个“Hello World” UILabel到画布中。


    add file's owner.png
    connect outlets.png

    然后修改AppDelegate.swift的第一个方法为如下代码:

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
            // Override point for customization after application launch.
            
            window = UIWindow(frame: UIScreen.mainScreen().bounds)
            window?.rootViewController = ViewController(nibName: "MainNib", bundle: nil)
            window?.makeKeyAndVisible()
            
            return true
        }
    

    运行程序,会看到和用storyboard相同的结果。


    至此,UI显示入门就告一段落。当然这里并没有深入涉及UIView的相关内容,这在以后的博客中会有所涉及。

    相关文章

      网友评论

      • 八月玄鸟:脑图是用什么画的很清爽
        段子周:@八月玄鸟 naotu.baidu.com 功能一般 但是看重它的在线同步
      • 61019d6b0f44:虽然我太小看不懂,但是也是作者辛辛苦苦写的,先点个赞。
        20c0b23aced4:hello kid
        61019d6b0f44: @段子周 有你这样子叫的吗?😖😖😖
        段子周:@我可是帅哥嘞 小朋友 你好
      • 59442f354c98:不错 期待下面的内容

      本文标题:[iOS UI] 显示

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