Frage

I am trying to use NSPopUpButtons in my OSX program. In order to use KVO for its string and its index, I wrote a custom class (DLPopUpButtonManager).

@interface DLPopUpButtonManager : NSObject

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

@end

That class works fine, when used only once in the program. But… When I use more than one instance their contentArray is shared, meaning the two contentArrays point to the same instance. Huh?? That totally confuses me. (Encapsulation, etc.)

I have two NSPopUpButtons that each are connected to an objects of class DLPopUpButtonManager. Those two classes are instantiated in Interface Builder though two objects. And in my AppDelegate I initialize them.

@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];
}

I find that both instances (confusingly and unwanted) use the same contentArray.

I investigated using breakpoints and saw that I have indeed two separate instances of DLPopUpButtonManager, but their contentArrays have the same pointer value.

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)

I can’t find anything like that through Google or here on SO. Who can tell me, what I am doing wrong here? I uploaded a little sample program to GitHub (https://github.com/donnerluetjen/PopUpButtonEtude).

Thanks for any input on that issue.

War es hilfreich?

Lösung

Try moving the underlying ivars for your your array and selection index properties into a private extension in the .m file, to ensure that they are not in fact static variables.

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

Andere Tipps

Thanks to tjboneman I could solve my problem, and I read some more about instance variables and static instance variables. Here is what I found after some serious searching:

From Apple's docs, The Objective-C Language | Defining a Class:

Class Interface

...

Note: Historically, the interface required declarations of a class’s instance variables, the data structures that are part of each instance of the class. These were declared in braces after the @interface declaration and before method declarations:

@interface ClassName : ItsSuperclass
{
    // Instance variable declarations.
}
// Method and property declarations.
@end

Instance variables represent an implementation detail, and should typically not be accessed outside of the class itself. Moreover, you can declare them in the implementation block or synthesize them using declared properties. Typically you should not, therefore, declare instance variables in the public interface and so you should omit the braces.

...

Class Implementation

The definition of a class is structured very much like its declaration. It begins with an @implementation directive and ends with the @end directive. In addition, the class may declare instance variables in braces after the @implementation directive:

@implementation ClassName
{
    // Instance variable declarations.
}
// Method definitions.
@end

Thanks again, tjboneman for pointing me in the right direction.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top