在日常布局設(shè)計(jì)中,你肯定試過無(wú)數(shù)次在 storyboard 或者 nib 與 view controller 之間建立 view 的對(duì)象引用惶傻。創(chuàng)建引用時(shí)你一定會(huì)留意到,屬性前多了一個(gè) IBOutlet 的修飾符。它是什么囱桨?有什么用途?下面就介紹一下它的來(lái)歷秀撇。
IBOutlet
官方文檔 中對(duì)其定義是:
An outlet is a property of an object that references another object.
IBOutlet 是一個(gè)對(duì)象屬性超棺,用于引用另一個(gè)對(duì)象。但為什么要額外添加這個(gè)修飾符呢呵燕?@property
不就是聲明一個(gè)屬性了嗎棠绘?繼續(xù)往下看:
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 來(lái)記錄的。記錄在 nib 被加載時(shí)會(huì)被重新建立再扭,在包含 IBOutlet 聲明的對(duì)象與引用對(duì)象之間建立連接氧苍。
所以我們知道,IBOutlet 的記錄是記錄在 nib 文件中泛范。nib 文件其實(shí)是 XML 格式让虐,在添加了一個(gè)IBOutlet 之后,通過看 nib 文件的源代碼可以看到多了一行以下代碼:
property
對(duì)應(yīng) controller 里的屬性名字罢荡,destination
我沒有考究赡突,我認(rèn)為應(yīng)該是指向?qū)?yīng)的 controller,id
應(yīng)該是對(duì)應(yīng)這個(gè) IBOutlet 記錄的 id区赵。
這下就明白了:在 nib 被加載時(shí)惭缰,runtime 通過這些 IBOutlet 記錄來(lái)尋找到 controller 里的 IBOutlet 屬性聲明并建立連接,所以后續(xù)你就可以通過這些屬性來(lái)使用對(duì)應(yīng)的 view 對(duì)象笼才。
注意:官方文檔中有這么一段話:
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 會(huì)占用內(nèi)存漱受!如果一個(gè) view 集合包含了很多 view,出于內(nèi)存考慮骡送,其中一種做法是可以通過 tag
來(lái)辨別不同的 view拜效,或者直接通過代碼實(shí)例化 view 并建立引用,這樣就能避免 IBOutlet 的過度使用各谚。
說(shuō)實(shí)話對(duì)于 IBOutlet 會(huì)占用內(nèi)存的現(xiàn)象我是挺驚訝的紧憾,畢竟這是官方推行的布局方式,按理說(shuō)會(huì)做足優(yōu)化昌渤。至于它的影響有多大赴穗,我沒有去深入探討,有興趣的小伙伴可以研究研究膀息,有什么發(fā)現(xiàn)懇請(qǐng)分享一下成果般眉,不勝感激!
IBAction
在 iOS 與 macOS 開發(fā)中潜支,IBAction 是 target-action 設(shè)計(jì)模式里的概念甸赃。先看 target-action 設(shè)計(jì)模式的官方解釋:
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 機(jī)制用于一個(gè)對(duì)象(iOS 中通常是 UIControl
對(duì)象)在觸發(fā)某種事件時(shí)冗酿,通過發(fā)送特定的動(dòng)作信息(action message)給目標(biāo)對(duì)象(target)埠对,來(lái)實(shí)現(xiàn)彼此聯(lián)系的目的络断。
在 iOS 開發(fā)中,這是相當(dāng)常見的 UIControl
組件與 controller 之間進(jìn)行聯(lián)系的機(jī)制项玛。在代碼中貌笨,可以通過 addTarget(_:action:for:)
方法給 UIControl
組件(如 UIButton
)添加特定事件(如 touchUpInside
)被觸發(fā)時(shí),需要調(diào)用 controller 的哪個(gè)方法襟沮。如果通過 Interface Builder 來(lái)建立 UIControl
組件與 controller 之間的 target-action 機(jī)制的話锥惋,方法一般需要遵循一定的格式,如:
Swift:
@IBAction func doSomething(_ sender: Any) {
}
ObjC:
- (IBAction)doSomething:(id)sender;
方法傳進(jìn)來(lái)的 sender
是被觸發(fā)事件的 UIControl
對(duì)象开伏,因此開發(fā)者可以通過此對(duì)象獲取到事件觸發(fā)時(shí)更詳細(xì)的上下文信息膀跌。這里的 IBAction
的作用與上文講的 IBOutlet
類似,用于 nib 文件在加載時(shí)把 UIControl
組件的 target-action 配置記錄與 controller 的方法匹配固灵。通過 Interface Builder 添加了一條 target-action 記錄后淹父,查看 nib 文件的源代碼格式可以看到一條類似下面的記錄:
selector
即方法名稱,destination
是目標(biāo)對(duì)象(不明白為什么是 -1)怎虫,eventType
是 UIControlEvents
的值的組合。通過這樣困介,視圖布局連同與 controller 之間的聯(lián)系就可以相對(duì)直觀地建立起來(lái)大审。