美文网首页
iOS - 关于 IBOutlet 和 IBAction

iOS - 关于 IBOutlet 和 IBAction

作者: DesmondDAI | 来源:发表于2018-01-08 00:50 被阅读346次

    在日常布局设计中,你肯定试过无数次在 storyboard 或者 nib 与 view controller 之间建立 view 的对象引用。创建引用时你一定会留意到,属性前多了一个 IBOutlet 的修饰符。它是什么?有什么用途?下面就介绍一下它的来历。

    IBOutlet

    官方文档 中对其定义是:

    An outlet is a property of an object that references another object.

    IBOutlet 是一个对象属性,用于引用另一个对象。但为什么要额外添加这个修饰符呢?@property 不就是声明一个属性了吗?继续往下看:

    The reference is archived through Interface Builder. The connections between the containing object and its outlets are reestablished every time the containing object is unarchived from its nib file.

    IBOutlet 的引用是通过 Interface Builder 来记录的。记录在 nib 被加载时会被重新建立,在包含 IBOutlet 声明的对象引用对象之间建立连接。

    所以我们知道,IBOutlet 的记录是记录在 nib 文件中。nib 文件其实是 XML 格式,在添加了一个IBOutlet 之后,通过看 nib 文件的源代码可以看到多了一行以下代码:


    IBOutlet 的源码声明

    property 对应 controller 里的属性名字,destination 我没有考究,我认为应该是指向对应的 controller,id 应该是对应这个 IBOutlet 记录的 id。

    这下就明白了:在 nib 被加载时,runtime 通过这些 IBOutlet 记录来寻找到 controller 里的 IBOutlet 属性声明并建立连接,所以后续你就可以通过这些属性来使用对应的 view 对象。


    注意:官方文档中有这么一段话:

    The more outlets an object has, the more memory it takes up. If there are other ways to obtain a reference to an object, such as finding it through its index position in a matrix, or through its inclusion as a function parameter, or through use of a tag (an assigned numeric identifier), you should do that instead.

    IBOutlet 会占用内存!如果一个 view 集合包含了很多 view,出于内存考虑,其中一种做法是可以通过 tag 来辨别不同的 view,或者直接通过代码实例化 view 并建立引用,这样就能避免 IBOutlet 的过度使用。

    说实话对于 IBOutlet 会占用内存的现象我是挺惊讶的,毕竟这是官方推行的布局方式,按理说会做足优化。至于它的影响有多大,我没有去深入探讨,有兴趣的小伙伴可以研究研究,有什么发现恳请分享一下成果,不胜感激!

    IBAction

    在 iOS 与 macOS 开发中,IBAction 是 target-action 设计模式里的概念。先看 target-action 设计模式的官方解释:

    Target-action is a design pattern in which an object holds the information necessary to send a message to another object when an event occurs. The stored information consists of two items of data: an action selector, which identifies the method to be invoked, and a target, which is the object to receive the message. The message sent when the event occurs is called an action message. Although the target can be any object, even a framework object, it is typically a custom controller that handles the action message in an application-specific way.

    意思就是,target-action 机制用于一个对象(iOS 中通常是 UIControl 对象)在触发某种事件时,通过发送特定的动作信息(action message)给目标对象(target),来实现彼此联系的目的。

    在 iOS 开发中,这是相当常见的 UIControl 组件与 controller 之间进行联系的机制。在代码中,可以通过 addTarget(_:action:for:) 方法给 UIControl 组件(如 UIButton)添加特定事件(如 touchUpInside)被触发时,需要调用 controller 的哪个方法。如果通过 Interface Builder 来建立 UIControl 组件与 controller 之间的 target-action 机制的话,方法一般需要遵循一定的格式,如:

    Swift:

    @IBAction func doSomething(_ sender: Any) {
    }
    

    ObjC:

    - (IBAction)doSomething:(id)sender;
    

    方法传进来的 sender 是被触发事件的 UIControl 对象,因此开发者可以通过此对象获取到事件触发时更详细的上下文信息。这里的 IBAction 的作用与上文讲的 IBOutlet 类似,用于 nib 文件在加载时把 UIControl 组件的 target-action 配置记录与 controller 的方法匹配。通过 Interface Builder 添加了一条 target-action 记录后,查看 nib 文件的源代码格式可以看到一条类似下面的记录:

    IBAction 记录

    selector 即方法名称,destination 是目标对象(不明白为什么是 -1),eventTypeUIControlEvents 的值的组合。通过这样,视图布局连同与 controller 之间的联系就可以相对直观地建立起来。

    参考

    IBOutlet 的官方文档
    IBAction 的官方文档

    相关文章

      网友评论

          本文标题:iOS - 关于 IBOutlet 和 IBAction

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