Need to declare a public instance variable in Objective-C
Asked Answered
M

1

12

I'm trying to declare some instance variables for a custom button class in Objective-C (for iOS):

@interface PatientIDButton : UIButton {
    NSUInteger patientID;
    NSString * patientName;
}
@end

However, these are now private and I need them accessible to other classes. I guess I could make accessor functions for them, but how would I make the variables themselves public?

Mochun answered 7/7, 2013 at 2:38 Comment(3)
FYI, making ivars public is very unidiomatic and depending on whether you are using ARC can greatly complicate your memory management.Edi
What @chuck said. Direct access to instance variables is a really bad pattern to use. Breaks encapsulation and defeats things like KVO.Summersault
You really shouldn't be using explicit ivars at all. Apple, as I understand, now encourages (and themselves use) properties exclusively. And with implicit synthesizing, they're trivial and powerful.Nannie
M
19

To make instance variables public, use @public keyword, like this:

@interface PatientIDButton : UIButton {
    // we need 'class' level variables
    @public NSUInteger patientID;
}
@end

Of course you need to remember all the standard precautions of exposing "raw" variables for public access: you would be better off with properties, because you would retain flexibility of changing their implementation at some later time.

Finally, you need to remember that accessing public variables requires a dereference - either with an asterisk or with the -> operator:

PatientIDButton *btn = ...
btn->patientID = 123; // dot '.' is not going to work here.
Mouthpart answered 7/7, 2013 at 2:45 Comment(8)
This seems way more complicated than needed. Why not just declare a public property in the header file? @property NSUInteger patientID. Then each instance of the button can be access through standard Obj-C methods. myButton.patientID.Elviselvish
Yes, a property makes sense as well. Thanks all!Mochun
Do not use the -> operator to access ivars.Summersault
@Summersault Why, should (*btn).patientID be used instead?Mouthpart
@dasblinkenlight No -- you shouldn't be assigning directly to instance variables at all outside of the class's implementation itself (where you don't need to use -> at all). Going directly breaks encapsulation.Summersault
@Summersault Ah, I see your point. I agree, one should avoid exposing "raw" variables. I do not understand why the designers of Objective-C added this feature in the first place.Mouthpart
@dasblinkenlight: When Objective-C was created, it was a very different world. It was originally a tiny Smalltalk-like object system on top of C, very much like C With Classes (which evolved into C++). There was no NSObject, there wasn't even any retain or release, and the overhead of message calls was considered rather decadent.Edi
@Summersault and in the context of tests, sometimes you want to test if custom getters or setters are doing the right thing related to the ivar, so what do you recommend?Seersucker

© 2022 - 2024 — McMap. All rights reserved.