在 Interface Builder 中实例化同一类的多个对象会导致共享属性
Posted
技术标签:
【中文标题】在 Interface Builder 中实例化同一类的多个对象会导致共享属性【英文标题】:Instantiating multiple objects of the same class in Interface Builder results in shared property 【发布时间】:2014-03-17 12:59:30 【问题描述】:我正在尝试在我的 OSX 程序中使用 NSPopUpButtons。为了将 KVO 用于其字符串和索引,我编写了一个自定义类(DLPopUpButtonManager)。
@interface DLPopUpButtonManager : NSObject
@property NSArray *contentArray;
@property NSString *selectionString;
@property NSNumber *selectionIndex;
@end
当在程序中只使用一次时,该类工作正常。但… 当我使用多个实例时,它们的 contentArray 是共享的,这意味着两个 contentArray 指向同一个实例。啊??这完全让我感到困惑。 (封装等)
我有两个 NSPopUpButton,每个都连接到 DLPopUpButtonManager 类的对象。这两个类通过两个对象在 Interface Builder 中实例化。然后在我的 AppDelegate 中初始化它们。
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (weak) IBOutlet DLPopUpButtonManager *pUBM_1;
@property (weak) IBOutlet DLPopUpButtonManager *pUBM_2;
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
[self.pUBM_1 setContentArray:[NSArray arrayWithObjects:@"Female", @"Male", nil]];
[self.pUBM_2 setContentArray:[NSArray arrayWithObjects:@"Tall", @"Short", nil]];
[self showDetails:nil];
我发现两个实例(令人困惑和不需要)使用相同的 contentArray。
我使用断点进行了调查,发现我确实有两个单独的 DLPopUpButtonManager 实例,但它们的 contentArrays 具有相同的指针值。
Printing description of $20: <DLPopUpButtonManager: 0x6080000100b0>
Printing description of $23: <DLPopUpButtonManager: 0x6080000100c0>
Printing description of $25: <__NSArrayI 0x600000223ba0>
(
Tall,
Short
)
Printing description of $24: <__NSArrayI 0x600000223ba0>
(
Tall,
Short
)
(lldb)
我无法通过 Google 或在 SO 上找到类似的内容。谁能告诉我,我在这里做错了什么? 我上传了一个小示例程序到 GitHub (https://github.com/donnerluetjen/PopUpButtonEtude)。
感谢您对此问题的任何意见。
【问题讨论】:
显而易见的问题,但是,您没有为两者分配相同的数组是吗? (我没有看过示例项目)。 @JoeFryer:我添加了更多细节。我用两个不同的数组初始化它们。 【参考方案1】:尝试将您的数组和选择索引属性的基础 ivars 移动到 .m 文件中的私有扩展名中,以确保它们实际上不是静态变量。
@interface DLPopUpButtonManager ()
NSArray *_contentArray;
NSUInteger _selectionIndex;
【讨论】:
谢谢 tjboneman。我不知道。我会读一遍关于实例变量和静态的声明。 我在这里找到了更多信息:在 Apple 的文档中,The Objective-C Language | Defining a Class。实际上,我更喜欢在实现文件中声明实例变量。一旦我可以自己发布答案,我会发布更多内容。【参考方案2】:感谢 tjboneman,我可以解决我的问题,并且我阅读了更多关于实例变量和静态实例变量的信息。这是我经过认真搜索后发现的:
来自 Apple 的文档,The Objective-C Language | Defining a Class:
类接口
...
注意:从历史上看,接口需要声明类的实例变量,即属于类的每个实例的数据结构。这些是在@interface 声明之后和方法声明之前用大括号声明的:
@interface ClassName : ItsSuperclass
// Instance variable declarations.
// Method and property declarations.
@end
实例变量代表一个实现细节,通常不应在类本身之外访问。此外,您可以在实现块中声明它们或使用声明的属性合成它们。因此,通常不应在公共接口中声明实例变量,因此应省略大括号。
...
类实现
类的定义与它的声明非常相似。它以@implementation 指令开始,以@end 指令结束。此外,该类可以在@implementation 指令之后用大括号声明实例变量:
@implementation ClassName
// Instance variable declarations.
// Method definitions.
@end
再次感谢 tjboneman 为我指明了正确的方向。
【讨论】:
以上是关于在 Interface Builder 中实例化同一类的多个对象会导致共享属性的主要内容,如果未能解决你的问题,请参考以下文章
在 Interface Builder 中嵌套 XIB/通过引用嵌入
Interface Builder 和 Cocoa:在 App Controller 类后面连接
不使用 Interface Builder 将 NIB 转换为 XIB
在 Interface Builder 中设置 Nib Name 字段时出现异常