Cocoa编程之IBAction和IBOutlet含义
IBAction / IBOutlet / IBOutletCollection
In programming, what often begins as a necessary instruction eventually becomes a vestigial cue for humans. In the case of Objective-C, #pragma directives, method
type encodings , and all but the most essentialstorage classeshave been rendered essentially meaningless, as the compiler becomes increasingly sophisticated. Discarded and disregarded during the compilation phase, they nonetheless remain useful to the
development process as a whole, insofar as what they can tell other developers about the code itself.
For developers just starting with Cocoa & Cocoa Touch, the IBAction , IBOutlet ,
and IBOutletCollection macros
are particularly bewildering examples of this phenomenon. As we'll learn in this week's article, though having outgrown their technical necessity, they remain a vibrant tradition in the culture of Objective-C development.
Unlike othertwo-letter prefixes, IB does
not refer to a system framework, but rather Interface Builder.
Interface Builder can trace its roots to the halcyon days of Objective-C, when it and Project Builder comprised the NeXTSTEP developer tools (circa
1988). Before it was subsumed into Xcode 4, Interface Builder remained remarkably unchanged from its 1.0 release. An iOS developer today would feel right at home on a NeXTSTEP workstation, control-dragging views into outlets.
Back when they were separate applications, it was a challenge to keep the object graph represented in a .nib document
in Interface Builder synchronized with its corresponding .h & .m files
in Project Builder (what would eventually become Xcode). IBOutlet and IBAction were
used as keywords, to denote what parts of the code should be visible to Interface Builder.
IBAction and IBOutlet are,
themselves, computationally meaningless, as their macro definitions (in UINibDeclarations.h )
demonstrate:
#define IBAction void
#define IBOutlet
Well actually, there's more than meets the eye. Scrying the Clang source code , we see that they're actually defined by attribute-backed
attributes:
#define IBOutlet __attribute__((iboutlet))
#define IBAction __attribute__((ibaction))
IBAction
As early as 2004 (and perhaps earlier), IBAction was
no longer necessary for a method to be noticed by Interface Builder. Any method with a signature - would be visible in the outlets pane.
(void){name}:(id)sender
Nevertheless, many developers find it useful to still use the IBAction return
type in method declarations to denote that a particular method is connected to an outlet. Even for projects not using Storyboards / XIBs may choose to employ IBAction to
call out target / action methods.
Naming IBAction Methods
Thanks to strong, and often compiler-enforced conventions, naming is especially important in Objective-C, so the question of how to name IBAction methods is one not taken lightly. Though there is some disagreement, the preferred convention is as follows:
- Return type of
IBAction. - Method name of an active verb, describing the specific action performed.Method names like
didTapButton:ordidPerformAction:sound
more like things adelegatemight
be sent. - Required
senderparameter
of typeid. All
target / action methods will pass thesenderof
the action (usually the responder) to methods that take a parameter. If omitted in the method signature, things will still work. - Optional event parameter of type
UIEvent, named
*withEvent:(iOS
only) . In UIKit, a secondUIEventparameter, corresponding to the touch, motion, or remote control event triggering the responder, will be passed to target / action methods accepting this second parameter. The convention is to use
*withEvent:in
the method signature, to match theUIResponderAPIs.
For example:
// YES
- (IBAction)refresh:(id)sender;
- (IBAction)toggleVisibility:(id)sender
withEvent:(UIEvent *)event;
// NO
- (IBAction)peformSomeAction;
- (IBAction)didTapButton:(id)sender;
IBOutlet
Unlike IBAction , IBOutlet is
still required for hooking up properties in code with objects in a Storyboard or XIB.
An IBOutlet connection is usually
established between a view or control and its managing view controller (this is often done in addition to any IBAction s
that a view controller might be targeted to perform by a responder). However, an IBOutlet can
also be used to expose a top-level property, like another controller or a property that could then be accessed by a referencing view controller.
When to use @property or ivar
As with anything in modern Objective-C, properties are preferred to direct ivar access . The same is true of IBOutlet s:
// YES
@interface GallantViewController : UIViewController
@property (nonatomic, weak) IBOutlet UISwitch *switch;
@end
// NO
@interface GoofusViewController : UIViewController {
IBOutlet UISwitch *_switch
}
@end
With the advent of ARC , it became possible to reference an IBOutlet from
an instance variable. However, since properties are the conventional way to expose and access members of a class, both externally and internally, they are preferred in this case as well, if only for consistency.
When to use weak or strong
One unfortunate consequence (if you want to call it that) of ARC is the ambiguity of when a IBOutlet @property should
be declared as weak or strong .
The ambiguity arises from the fact that most outlets have no discernible behavioral differences between weak or strong —it
just works.
...except when it doesn't... and things crash, or the compiler warns about weakor strong use.
So what should one do? Always declare IBOutlet properties
as weak , except when they
need to be strong ,
as explained by Apple in their Resource Programming Guide section on Nib Files :
Outlets should be changed to strong when
the outlet should be considered to own the referenced object:
- This is often the case with File’s Owner—top level objects in a nib file are frequently considered to be owned by the
File’s.
Owner - You may in some situations need an object from a nib file to exist outside of its original container. For example, you might have an outlet for a view that can be temporarily removed from its initial view
hierarchy and must therefore be maintained independently.
The reason why most IBOutlet views
can get away with weak ownership
is that they are already owned within their respective view hierarchy, by their superview. This chain of ownership eventually works its way up to the view owned
by the view controller itself. Spurious use of strong ownership
on a view outlet has the potential to create a retain cycle.
IBOutletCollection
IBOutlet 's obscure step-cousin-in-law-once-removed
is IBOutletCollection . Introduced
in iOS 4, this pseudo-keyword allows collections of IBOutlet s
to be defined in Interface Builder, by dragging connections to its collection members.
IBOutletCollection is #define 'd
in UINibDeclarations.h as:
#define IBOutletCollection(ClassName)
...which is defined in a much more satisfying way, again, in the Clang source code :
#define IBOutletCollection(ClassName) __attribute__((iboutletcollection(ClassName)))
Unlike IBAction or IBOutlet , IBOutletCollection takes
a class name as an argument, which is, incidentally, as close to Apple-sanctioned generics as one gets in Objective-C.
As a top-level object, an IBOutletCollection @property should
be declared strong , with an NSArray type:
*
@property (nonatomic, strong) IBOutletCollection(UIButton) NSArray *buttons;
There are two rather curious things to note about an IBOutletCollectionarray:
- Its order is not necessarily guaranteed . The order of an outlet collection appears to be roughly the order in which their connections are established in Interface Builder. However, there
are numerous reports of that order changing across versions of Xcode, or as a natural consequence of version control. Nonetheless, having code rely on a fixed order is strongly discouraged. - No matter what type is declared for the property, an
IBOutletCollectionis
always anNSArray.
In fact, any type can be declared:NSSet,
*id <NSFastEnumeration>—heck,
evenUIColor *! No matter what
you put, anIBOutletCollectionwill
always be stored as anNSArray,
so you might as well have that type match up in your declaration to avoid compiler warnings.
With the advent of Objective-Cobject literals, IBOutletCollection has
fallen slightly out of favor—at least for the common use case of convenience accessors, as in:
for (UILabel *label in labels) {
label.font = [UIFont systemFontOfSize:14];
}
Since declaring a collection of outlets is now as easy as comma-delimiting them within @[] ,
it may make just as much sense to do that as create a distinct collection.
Where IBOutletCollection really
shines is how it allows for multiple to define a unique collection of outlets under a shared identifier. Another advantage over a code-defined NSArray literal
is that a collection can contain outlets that themselves are not connected to File's .
Owner
The next time you're managing a significant or variable number of outlets in an iOS view, take a look at IBOutletCollection .
IBAction , IBOutlet ,
and IBOutletCollection play
important roles in development, on both the compiler level and human level . As Objective-C continues to rapidly evolve as a platform, it is likely that they may someday be as completely vestigial as the wings of flightless birds or eyes of cavefish. For now,
though, it's important to understand what they are, and how to use them, if you plan on creating apps in any capacity.
Cocoa编程之IBAction和IBOutlet含义的更多相关文章
- 深入浅出Cocoa多线程编程之 block 与 dispatch quene
深入浅出 Cocoa 多线程编程之 block 与 dispatch quene 罗朝辉(http://www.cppblog.com/kesalin CC 许可,转载请注明出处 block 是 Ap ...
- [深入浅出Cocoa]iOS网络编程之Socket
http://blog.csdn.net/kesalin/article/details/8798039 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] [深入浅出Co ...
- [Cocoa]深入浅出Cocoa多线程编程之 block 与 dispatch quene
深入浅出 Cocoa 多线程编程之 block 与 dispatch quene 罗朝辉(http://www.cppblog.com/kesalin CC 许可,转载请注明出处 block 是 Ap ...
- iOS多线程编程之NSThread的使用
目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...
- iOS多线程编程之NSThread的使用(转)
本文由http://blog.csdn.net/totogo2010/原创 1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation ...
- [转]iOS多线程编程之NSThread的使用
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...
- iOS多线程编程之NSThread的使用(转载)
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1.NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的 ...
- C++混合编程之idlcpp教程(一)
我是C++语言的忠实拥趸,由于在上学时经历了资源匮乏的DOS时代,对C/C++这种更加接近硬件的语言由衷的喜爱.一直以来也是已C++作为工作的语言,对别的语言那是不屑一顾.在java火爆流行的时候,没 ...
- ##DAY13——可视化编程之XIB
##DAY13——可视化编程之XIB 1.关联控件 2.关联事件 3.关联手势 4.关联代理 这个时候即使不给控制器用下面方法添加代理,代理方法也是可以使用的,只是没有方法提示: 其他重要地方: #i ...
随机推荐
- 返回present的根
//返回四大tab页面 + (void)gobackToTabarController { UINavigationController* selectedTabNavController = (UI ...
- Dynamics CRM2015 非基础语言环境下产品无法新建的问题
该现象出现在2015版本上,之前从没注意过这个问题不知道以前的版本是否存在. 我的安装包的基础语言是中文,第一张图有添加产品的按钮,切换到英文环境下后就没有了,一开始以为是系统做了隐藏处理,但用工具查 ...
- iOS9 中关闭ATS的方法
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) iOS9中增加了系统的安全性,你会发现默认情况下打开非http ...
- [django]添加自定义template filter标签
看文档templatetag 直接放在app下的templatetag 文件夹下就好,这里想放到一个公共的目录下,然后写下简单的自定义tag的模板. django1.6 创建 在项目目录下建立如下的文 ...
- android插件化之路
概论 插件式开发通俗的讲就是把一个很大的app分成n多个比较小的app,其中有一个app是主app.基本上可以理解为让一个apk不安装也可以被运行.只不过这个运行是有很多限制的运行,所以才叫插件. ...
- 【java线程系列】java线程系列之java线程池详解
一线程池的概念及为何需要线程池: 我们知道当我们自己创建一个线程时如果该线程执行完任务后就进入死亡状态,这样如果我们需要在次使用一个线程时得重新创建一个线程,但是线程的创建是要付出一定的代价的,如果在 ...
- hadoop cdh5的pig隐式转化(int到betyarray)不行了
cdh3上,pig支持int到chararray的隐式转化,但到cdh5不行. pig code is as follows: %default Cleaned_Log /user/usergroup ...
- 新手推荐:Hadoop安装教程_单机/伪分布式配置_Hadoop-2.7.1/Ubuntu14.04
下述教程本人在最新版的-jre openjdk-7-jdk OpenJDK 默认的安装位置为: /usr/lib/jvm/java-7-openjdk-amd64 (32位系统则是 /usr/lib/ ...
- 认识 SurfaceView
SurfaceView是基于View视图进行扩展的视图类,适用于2D游戏开发,主要特点有: [1]surfaceView中对于画布的重绘是由一个新的线程去绘制,因此可以处理一些耗时的操作 [2]sur ...
- Mahout 系列之----共轭梯度
无预处理共轭梯度 要求解线性方程组 ,稳定双共轭梯度法从初始解 开始按以下步骤迭代: 任意选择向量 使得 ,例如, 对 若 足够精确则退出 预处理共轭梯度 预处理通常被用来加速迭代方法的收敛.要使用预 ...