Undeclared ivars? - objective-c

I've come across Objective-C code that declares a variable right below the #implementation line in a .m file and not in the #interface block of the .h file. It then proceeds to use it like a private ivar. I haven't been able to find documentation about declaring variables this way and would like to know the impact.
Example:
.h
#interface MyClass {
#private
int _myPrivInt1;
}
#end
.m
#implementation
int _myPrivInt2;
#end
Questions:
What is the technical difference between these two variables?
Is it the same as declaring an ivar in the .h #interface block using the #private modifier or is it more like a C global variable?
Are there any implications when declaring a variable this way?
Should it be avoided?
Is there a term for declaring variables like _myPrivInt2 that would have made my googling a bit more successful?

You must declare instance variables in interface block.
#implementation
int _myPrivInt2;
#end
Declaring variable this way you do not actually declare iVar for your class. _myPrivInt2 will be a global variable and can be accessed from any part of your code using extern declaration:
// SomeOtherFile.m
extern int _myPrivInt2;
...
_myPrivInt2 = 1000;
You can check - your _myPrivInt2 variable will be equal 1000 after code in SomeOtherFile.m executes.
You can also specify static linkage specifier to your _myPrivInt2 so it will be accessible inside current translation unit only
#implementation
static int _myPrivInt2; // It cannot be accessed in other files now
#end

Related

How to add instance variables or properties to an XCTestCase?

I just learned, that I must declare instance variables and properties in a header file in Objective-C. So now i want to add instance variables to my XCTestCase subclass — but it turns out, XCTestCases come without header files.
How do i declare instance variables in my test cases?
You don't have to declare them in the header file at all. Instance variables and properties are commonly added within a private category in the implementation file:
#interface MyClass () {
BOOL _someVar;
}
#property NSString *someOtherVar;
- (void)_aPrivateMethod:(id)something;
#end
#implementation MyClass
...
#end

Objective-C: Different ways of declaring private variables. Any differences between them?

I have thought of different ways of declaring private variables. I want to know whether there are any differences between them.
First way:
//In .h file
#interface DataExtract : NSObject
{
#private
double test;
}
Second way:
//In .m file. test is not declared in .h file
static double test;
Third way:
//In .m file. test is not declared in .h file
double test;
Any help would be much appreciated. Thank you.
All of them are not a good solution if you want an ivar.
I would even tend to only use properties with autogenerated ivars in an class extension in the implementation file only one line (#synthesize is automatically generated in Objective-C 3.0).
First way:
Yes this is an ivar, but you shouldn't declare it in the header file, if you declare it #private, then use the #implementation {...} block. In the implementation block you don't need to declare it #private, because it defaults to #protected, but in the implementation block it is not visible for subclasses
Second way:
That is a variable only visible in the translation unit, here the .m file itself. It is not global for the whole app. The value is persistent for every instance of your class, so it is no ivar (instance variable).
Third way:
That is also no ivar, it is a variable which defaults to extern, because you did not write static. That means it is in the global symbol table and can be used in other translation units /files if they #import/#include the .m file.
Your second and third examples are not instance variables, but global variables (with differing scope) and the same value will be shared across the entire process.
You can declare a private #interface in the .m file.
//DataExtract.m
#interface DataExtract ()
//your variables
#end
#implementation DataExtract
#end
For more info you can go here
Is there a reason you want to use just an instance variable, instead of a property?
You can declare a private property like so:
// Private Interface in .m file
#interface DataExtract()
#property (nonatomic) double test;
#end
Edit:
If you do want to use a private ivar, instead of a property, you could do it like so:
// Private Interface in .m file
#interface DataExtract() {
double test;
}
#end

Can the ivar variable created automatically by properties accessible by the child class? [duplicate]

Since recent runtimes in iOS, we are able to define properties that will generate accessors for instance variables. From what I understand, it is not mandatory to declare the instance variable used since it will be automatically done for us.
For example, if I write:
#interface MyFirstClass
#property (readonly, nonatomic) int size;
#end
and in the .m
#implementation MyFirstClass
#synthesize size;
#end
Then an instance variable named "size" will be added for me and a method called "-(int)size" will be implemented.
The problem is that when I create a second class MySecondClass which is a subclass of MyFirstClass, it seems that I can't access the instance variable size within this subclass:
#interface MySecondClass : MyFirstClass
#end
#implementation MySecondClass
- (id)init {
if (self = [super init]) {
size = 10; // this yields and error
}
return self;
}
#end
Are the automatically created instance variables private? Is there a possibility to set them as protected so I can access them in subclasses?
I know there is the possibility to declare the instance variable myself, but I'm just wondering...
With a superclass like this it works: (Is it because it's expressly declared as protected?)
#interface MyFirstClass {
int size; // defined expressly and used as #protected
}
#property (readonly, nonatomic) int size;
#end
Thank you for your help!!
Nicolas.
Any instance variable not declared in the main interface is automatically private, and this cannot be overridden. If you try to use a scope modifier when defining instance variables in the implementation, you will get an error that the specification is inconsistent.
The reason for this is that there is usually only one class per implementation file, which means the compiler doesn't know about the instance variable when compiling other classes. If you have multiple classes in the same file, the compiler could know about it, but you still aren't allowed to override the scope. Possible reasons in this case could be for consistency, or just so the compiler doesn't have to look in so many places for instance variables.
Use:
self.size = 10;
That will map to setSize method.

What is the difference between the areas where you can declare instance variables in Objective-C? [duplicate]

Ever since starting to work on iOS apps and objective C I've been really puzzled by the different locations where one could be declaring and defining variables. On one hand we have the traditional C approach, on the other we have the new ObjectiveC directives that add OO on top of that. Could you folks helps me understand the best practice and situations where I'd want to use these locations for my variables and perhaps correct my present understanding?
Here's a sample class (.h and .m):
#import <Foundation/Foundation.h>
// 1) What do I declare here?
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
// 3) class-specific method / property declarations
#end
and
#import "SampleClass.h"
// 4) what goes here?
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
#implementation SampleClass
{
// 6) define ivars
}
// 7) define methods and synthesize properties from both public and private
// interfaces
#end
My understanding of 1 and 4 is that those are C-style file-based declarations and definitions that have no understanding whatsoever of the concept of class, and thus have to be used exactly how they would be used in C. I've seen them used for implementing static variable-based singletons before. Are there other convenient uses I'm missing?
My take from working with iOS is that ivars have been alost completely phased out outside of the #synthesize directive and thus can be mostly ignored. Is that the case?
Regarding 5: why would I ever want to declare methods in private interfaces? My private class methods seem to compile just fine without a declaration in the interface. Is it mostly for readability?
Thanks a bunch, folks!
I can understand your confusion. Especially since recent updates to Xcode and the new LLVM compiler changed the way ivars and properties can be declared.
Before "modern" Objective-C (in "old" Obj-C 2.0) you didn't have a lot of choices. Instance variables used to be declared in the header between the curly brackets { }:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#end
You were able to access these variables only in your implementation, but not from other classes. To do that, you had to declare accessor methods, that look something like this:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
- (int)myVar;
- (void)setMyVar:(int)newVar;
#end
// MyClass.m
#implementation MyClass
- (int)myVar {
return myVar;
}
- (void)setMyVar:(int)newVar {
if (newVar != myVar) {
myVar = newVar;
}
}
#end
This way you were able to get and set this instance variable from other classes too, using the usual square bracket syntax to send messages (call methods):
// OtherClass.m
int v = [myClass myVar]; // assuming myClass is an object of type MyClass.
[myClass setMyVar:v+1];
Because manually declaring and implementing every accessor method was quite annoying, #property and #synthesize were introduced to automatically generate the accessor methods:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#synthesize myVar;
#end
The result is much clearer and shorter code. The accessor methods will be implemented for you and you can still use the bracket syntax as before. But in addition, you can also use the dot syntax to access properties:
// OtherClass.m
int v = myClass.myVar; // assuming myClass is an object of type MyClass.
myClass.myVar = v+1;
Since Xcode 4.4 you don't have to declare an instance variable yourself anymore and you can skip #synthesize too. If you don't declare an ivar, the compiler will add it for you and it will also generate the accessor methods without you having to use #synthesize.
The default name for the automatically generated ivar is the name or your property starting with an underscore. You can change the generated ivar's name by using #synthesize myVar = iVarName;
// MyClass.h
#interface MyClass : NSObject
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#end
This will work exactly as the code above. For compatibility reasons you can still declare ivars in the header. But because the only reason why you would want to do that (and not declare a property) is to create a private variable, you can now do that in the implementation file as well and this is the preferred way.
An #interface block in the implementation file is actually an Extension and can be used to forward declare methods (not needed anymore) and to (re)declare properties. You could for instance declare a readonly property in your header.
#property (nonatomic, readonly) myReadOnlyVar;
and redeclare it in your implementation file as readwrite to be able to set it using the property syntax and not only via direct access to the ivar.
As for declaring variables completely outside of any #interface or #implementation block, yes those are plain C variables and work exactly the same.
First, read #DrummerB's answer. It a good overview of the whys and what you should generally do. With that in mind, to your specific questions:
#import <Foundation/Foundation.h>
// 1) What do I declare here?
No actual variable definitions go here (it's technically legal to do so if you know exactly what you're doing, but never do this). You may define several other kinds of things:
typdefs
enums
externs
Externs look like variable declarations, but they're just a promise to actually declare it somewhere else. In ObjC, they should only be used to declare constants, and generally only string constants. For instance:
extern NSString * const MYSomethingHappenedNotification;
You would then in your .m file declare the actual constant:
NSString * const MYSomethingHappenedNotification = #"MYSomethingHappenedNotification";
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
As noted by DrummerB, this is legacy. Don't put anything here.
// 3) class-specific method / property declarations
#end
Yep.
#import "SampleClass.h"
// 4) what goes here?
External constants, as described above. Also file static variables can go here. These are the equivalent of class variables in other languages.
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
Yep
#implementation SampleClass
{
// 6) define ivars
}
But very rarely. Almost always you should allow clang (Xcode) to create the variables for you. The exceptions are usually around non-ObjC ivars (like Core Foundation objects, and especially C++ objects if this is an ObjC++ class), or ivars that have weird storage semantics (like ivars that don't match with a property for some reason).
// 7) define methods and synthesize properties from both public and private
// interfaces
Generally you shouldn't #synthesize anymore. Clang (Xcode) will do it for you, and you should let it.
Over the last few years, things have gotten dramatically simpler. The side-effect is that there are now three different eras (Fragile ABI, Non-fragile ABI, Non-fragile ABI + auto-syntheisze). So when you see the older code, it can be a little confusing. Thus confusion arising from simplicity :D
I'm also pretty new, so hopefully I don't screw anything up.
1 & 4: C-style global variables: they have file wide scope. The difference between the two is that, since they're file wide, the first will be available to anyone importing the header while the second is not.
2: instance variables. Most instance variables are synthesized and retrieved/set through accessors using properties because it makes memory management nice and simple, as well as gives you easy-to-understand dot notation.
6: Implementation ivars are somewhat new. It's a good place to put private ivars, since you want to only expose what's needed in the public header, but subclasses don't inherit them AFAIK.
3 & 7: Public method and property declarations, then implementations.
5: Private interface. I always use private interfaces whenever I can to keep things clean and create a kind of black box effect. If they don't need to know about it, put it there. I also do it for readability, don't know if there are any other reasons.
This is an example of all kinds of variables declared in Objective-C. The variable name indicate its access.
File: Animal.h
#interface Animal : NSObject
{
NSObject *iProtected;
#package
NSObject *iPackage;
#private
NSObject *iPrivate;
#protected
NSObject *iProtected2; // default access. Only visible to subclasses.
#public
NSObject *iPublic;
}
#property (nonatomic,strong) NSObject *iPublic2;
#end
File: Animal.m
#import "Animal.h"
// Same behaviour for categories (x) than for class extensions ().
#interface Animal(){
#public
NSString *iNotVisible;
}
#property (nonatomic,strong) NSObject *iNotVisible2;
#end
#implementation Animal {
#public
NSString *iNotVisible3;
}
-(id) init {
self = [super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
iPrivate = #"iPrivate";
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
_iPublic2 = #"iPublic2";
iNotVisible = #"iNotVisible";
_iNotVisible2 = #"iNotVisible2";
iNotVisible3 = #"iNotVisible3";
}
return self;
}
#end
Note that the iNotVisible variables are not visible from any other class. This is a visibility issue, so declaring them with #property or #public doesn't change it.
Inside a constructor it's good practice to access variables declared with #property using underscore instead self to avoid side effects.
Let's try to access the variables.
File: Cow.h
#import "Animal.h"
#interface Cow : Animal
#end
File: Cow.m
#import "Cow.h"
#include <objc/runtime.h>
#implementation Cow
-(id)init {
self=[super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
//iPrivate = #"iPrivate"; // compiler error: variable is private
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
self.iPublic2 = #"iPublic2"; // using self because the backing ivar is private
//iNotVisible = #"iNotVisible"; // compiler error: undeclared identifier
//_iNotVisible2 = #"iNotVisible2"; // compiler error: undeclared identifier
//iNotVisible3 = #"iNotVisible3"; // compiler error: undeclared identifier
}
return self;
}
#end
We can still access the not visible variables using the runtime.
File: Cow.m (part 2)
#implementation Cow(blindAcess)
- (void) setIvar:(NSString*)name value:(id)value {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
object_setIvar(self, ivar, value);
}
- (id) getIvar:(NSString*)name {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
id thing = object_getIvar(self, ivar);
return thing;
}
-(void) blindAccess {
[self setIvar:#"iNotVisible" value:#"iMadeVisible"];
[self setIvar:#"_iNotVisible2" value:#"iMadeVisible2"];
[self setIvar:#"iNotVisible3" value:#"iMadeVisible3"];
NSLog(#"\n%# \n%# \n%#",
[self getIvar:#"iNotVisible"],
[self getIvar:#"_iNotVisible2"],
[self getIvar:#"iNotVisible3"]);
}
#end
Let's try to access the not visible variables.
File: main.m
#import "Cow.h"
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
Cow *cow = [Cow new];
[cow performSelector:#selector(blindAccess)];
}
}
This prints
iMadeVisible
iMadeVisible2
iMadeVisible3
Note that I was able to access the backing ivar _iNotVisible2 which is private to the subclass. In Objective-C all variables can be read or set, even those that are marked #private, no exceptions.
I didn't include associated objects or C variables as they are different birds. As for C variables, any variable defined outside #interface X{} or #implementation X{} is a C variable with file scope and static storage.
I didn't discuss memory management attributes, or readonly/readwrite, getter/setter attributes.

Objective C linker scoping

I ran into a situation where I had the following two implementations located in separate files:
ClassA.m
#implementation ClassA
int _x = 0;
#end
ClassB.m
#implementation ClassB
int _x = 0;
#end
When I compiled, the linker would state:
objective c duplicate symbol __x....
My solution was to mark both variables as static.
Is it then true that all member variables of Classes are just munged into the symbol table without their implementing Classname prepended (unless you mark them as static)? I'd find that hard to believe, otherwise I'd think using static would be the rule, not the exception...
You've not declared instance variables of the class there; you've declared global variables hence why the linker tells you that there's 2 symbols called _x.
You probably wanted to put them in your #interface for ClassA and ClassB.
Instance variable would be declared in the implementation file of your class, in the header file. You'll want the two class files to have something like this:
#interface ClassA : NSObject
{
int _x; // or NSInteger _x;
}