在Interface Builder中实例化同一个类的多个对象会产生共享属性

时间:2014-03-17 12:59:31

标签: objective-c cocoa interface-builder xcode5

我正在尝试在我的OSX程序中使用NSPopUpButtons。为了使用KVO作为其字符串及其索引,我编写了一个自定义类(DLPopUpButtonManager)。

@interface DLPopUpButtonManager : NSObject

  @property NSArray  *contentArray;
  @property NSString *selectionString;
  @property NSNumber *selectionIndex;

@end

当在程序中只使用一次时,该类工作正常。但… 当我使用多个实例时,他们的contentArray是共享的,这意味着两个contentArrays指向同一个实例。咦?这完全让我感到困惑。 (封装等)

我有两个NSPopUpButtons,每个都连接到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或此处找到类似的内容。谁能告诉我,我在这里做错了什么? 我将一些示例程序上传到GitHub(https://github.com/donnerluetjen/PopUpButtonEtude)。

感谢有关该问题的任何意见。

2 个答案:

答案 0 :(得分:0)

尝试将您的数组和选择索引属性的基础ivars移动到.m文件中的专用扩展中,以确保它们实际上不是静态变量。

@interface DLPopUpButtonManager (){
NSArray    *_contentArray;
NSUInteger _selectionIndex;
}

答案 1 :(得分:0)

感谢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指出我正确的方向。