难道一个IBOutlet需要一个属性与合成?(Does an IBOutlet needs to b

2019-06-17 23:36发布

在大多数例子我看到IBOutlets以下设置:



(Example A)

FooController.h:

@interface FooController : UIViewController {
    UILabel *fooLabel;
}

@property (nonatomic, retain) IBOutlet UILabel *fooLabel;

@end

FooController.m:

@implementation FooController

@synthesize fooLabel;

@end

但是,这也工作正常(注意:没有财产,没有合成):



(Example B)

FooController.h:

@interface FooController : UIViewController {
    IBOutlet UILabel *fooLabel;
}

@end

FooController.m:

@implementation FooController

@end

是否有限定IBOutlets如在实施例B中的任何缺点? 像内存泄漏? 似乎很好地工作,我宁愿不公开IBOutlets的公共属性,因为它们不被用作这样的,他们只在控制器实现使用。 定义它在三个地方没有真正的需要不打我非常DRY(不要重复自己)。

Answer 1:

在Mac OS X,IBOutlets连接是这样的:

  1. 查找名为集方法<OutletName> :. 如果它存在调用它。
  2. 如果没有方法存在,寻找名为实例变量<OutletName>,设置它不保留

在iPhone OS,IBOutlets连接是这样的:

  1. 调用[对象的setValue:outletValue forKey:@ “<OutletName>”]

设定值的关键的行为是做这样的事情:

  1. 查找名为集方法<OutletName> :. 如果它存在调用它。
  2. 如果没有方法存在,寻找名为实例变量<OutletName>,将其设置并保留它。

如果你使用的属性,你会掉进这两个平台上“ 寻找所谓一套方法<OutletName> ...”的情况。 如果只是用一个实例变量,那么你就会有不同的保留在Mac OS X VS iPhone OS /释放行为。 这没有什么错用一个实例变量,你只需要你的平台之间切换,以应对这种行为差异。

下面是完整的文档的链接只是这个话题。 https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6



Answer 2:

在Mac OS X,IBOutlets不会被默认保留。 这是iPhone OS的行为相反:在iPhone OS上,如果不申报则保留了财产,你必须释放在该属性dealloc方法。 此外,64位运行时可以使用合成属性声明实例变量。 这意味着,有一天实例变量(与IBOutlet )可以被省略。

由于这些原因,更均匀,兼容总是创建一个属性,并使用IBOutlet唯一的财产。 不幸的是,它也更详细。

在你的第一个例子中,你总是要释放出口中dealloc方法。 在第二个例子中,你必须释放仅与iPhone OS出口。



Answer 3:

最终的结果是完全一样的,但你必须保持一个几件事情:

  • 当作为出口使用实例字段,你不应该的dealloc释放他们。

  • 当使用具有(保留)属性的属性,则必须释放的dealloc属性(使用self.property=nil或通过释放衬里变量)。 这使得它作为是怎么回事了很多更加透明。

其实这一切都归结到同旧的规则:“ 你要释放你分配/保留 ”。 所以,如果你使用一个实例字段作为出口,你没有分配/保留它,所以你不应该将其释放。



Answer 4:

其可能的是这些实施例使用保留,因为样本代码被编程分配和初始化一个UILabel,然后将它添加到UIView的。 这对于许多例子的情况下,由于学习如何使用Interface Builder的往往不是他们的观点。

第二示例与IBOutlet中(没有属性和没有合成)用于当显影剂“分配”的界面生成器内的的UILabel(按钮,查看等) - 通过拖动IBOulet到标签或其他视图部件。 在我看来,前面的拖放操作(标签上查看)也添加子视图,标签到View - 等等。 标签由一个视图保留; 的视图被窗口保留; 窗口是由文件的所有者保留。 文件的所有者通常是您的文档,该文档在主启动了。

你会注意到,当你逐步执行程序(通过添加awakeFromNib

- (void)awakeFromNib
{
    [fooLabel blahblah];
}

该fooLabel已经有一个内存地址。

那是因为标签是使用未初始化,但是从的initWithCoder文件包(笔尖文件)初始化。 基本上反序列化FILESTREAM一个对象 - 然后设置IBOutlet中的变量。 (我们还在谈论IBOutlet中的方法)。

还要注意的是,上述的iOS方法使用键值的方法

  call [object setValue:outletValue forKey:@"<OutletName>"]

这是观测器/可观察图案。 该模式所需要的可观察对象引用在设置/阵列每个观察者。 值的变化将迭代设置/阵列,同样更新所有观察员。 这集将已经保持每个观察因而缺乏iOS中保留。

此外,剩下的就是投机。

看来情况下,当你使用Interface Builder然后

 @property (nonatomic, retain) IBOutlet UILabel *fooLabel;

应尽可能改为

@property (nonatomic, weak) IBOutlet UILabel *fooLabel;

或@属性(非原子,分配)IBOutlet中的UILabel * fooLabel;

然后它不需要在dealloc方法被释放。 再加上它会满足OSX和iOS的要求。

这是基于逻辑,我可以在这里失去了一些作品。

然而,如果认为是通过你的节目的生命持续的可能并不重要。 而在一个模式对话框的标签(开,关,开,关)实际上可能有过保留,每个周期泄漏。 那是因为(再次炒)各封闭对话框序列化为一个文件系统,因此仍然存在X,Y位置和大小,与它的子视图等一起和反序列化之后...上开下一届会议(反对说minimiz或隐藏。)



文章来源: Does an IBOutlet needs to be a property & synthesized?