I have a static variable that i want to access from another class in the same project in X-Code. I have declared it in the .h file AND the .m file, gave it a value, and then when i accessed the other class, i got an error message saying that:
"Property 'xx' is not found on object of type 'yy'"
i declared the variable as extern in the .h, and redeclared it as the variable type in the .m. I have tried to change it to static in the .h, but it still doesn't work. And yes, i have imported the file containing the variable, in case that is the problem.
Can anyone help me?
EDIT:
this is the code that i'm currently using:
source.h
static int anObject;
#interface source : NSObject
source.m
static int a = 2
#implementation source
destination.m
# include "source.h"
#implementation destination
- (void) anObjectTestFunction
{
printf("%d", source.anObject); //the first version
printf("%d", anObject); //second version
}
now after i went to the second version, the variable anObject in destination.h can be accessed, but its value is not 2, it's 0. I want it to follow the one i declared in source.h.
I am assuming the static variable declared in the .h file is outside the #interface. So something like:
static NSString *myObjectTest = #"Test";
#interface MyObject : NSObject
#end
If that is the case then you will not be able to access it using something like:
MyObject *obj = [[MyObject alloc] init];
[obj myObject]
or
obj.myObject
That is what is giving you the "Property 'xx' is not found on object of type 'yy'". That static variable is not a property on the object of MyObject.
That static variable is accessible like so myObjectTest as long as you import the .h file
Update
See Chuck's comment below why this is a bad idea to do this way.
You seem confused about what a static variable is. In other languages like Java or C++, "static" can mean one of two things. In a file or function scope, it means a variable scoped to either that file or function that exists for your program's entire lifetime. In a class scope, it means just a class variable.
C++ has both definitions, Java only has the second definition, but Objective-C only has the first definition: A static variable can only be used in the place where it's declared. There is no such thing as an "extern static" variable because the two are contradictory. You probably want either a global variable or a static variable with a class method to access it.
Could this be a namespace issue? Try fully qualifying your access. Posting an extract of your code would really be helpful though, I'm no good at clairvoyance :-)
Related
I'm new to Objective-C, and I can not understand what is the difference between the declaration of variables (firstString, secondString and thirdString) in MyClass.h:
#interface MyClass {
NSString *firstString;
}
#end
in MyClass.m:
#interface MyClass() {
NSString *secondString;
}
#end
#implementation MyClass
NSString *thirdString;
#end
I guess that the first and the second case is the same thing, but in what case it is better to use?
Thanks a lot!
firstString is declared in the header, the file which is #imported by other classes. It is exposed to other classes and can therefore be accessed by subclasses and, since the symbol is available in the header file, it will be simpler for external objects to alter through key-value coding.
secondString is declared in your implementation file. The () in #interface MyClass () signifies that this is a class extension. secondString will not be exposed to external classes (though, as with everything in Objective-C, you cannot consider it to be truly private).
The first and second variables will be instance variables, whereas the third one will be a file-scope global variable. Typically you should use instance variables and avoid using global variables.
There is no functional difference between the three, it's mainly visibility control.
The first one is declared in a public header of you class, that means that you want the programmers the know about the variable. If the access to this property is restricted (e.g. #private), it should not appear in public header anymore and you should use the second or forth option.
The second is declared in the class continuation, meaning that it is needed only by the implementation.
The third one is a global variable, something you should use only in exceptional cases.
Missing another option
#implementation MyClass {
NSString *thirdString;
}
#end
(allowed by the latest Apple compilers) is the same as 2, without the need to create the class continuation.
I declared an instance variable (not static), just a regular variable in the #implementation section. When I accessed that variable from several objects it appeared that all the objects were sharing the same variable, as if I had declared it static!
I then changed the instance variable to a (strong) property (defined in the .m file to make it private) and it started working as expected, with each object getting their own separate version of the property.
What was going on with that weird "sharing" behavior?
You didn't declare an instance variable. You defined a global variable. You did this:
#implementation MyObject
int myVariable;
but you should have done this:
#implementation MyObject {
int myVariable;
}
When you define a regular var in the #implementation, you define a global variable. For example, in a.m, you define:
#implementation classA
int tryMe = 99;
Then in b.m, you use also use tryMe:
#implementation classB
-(void) func {
extern int tryMe;
NSLog(#"%i", tryMe); // This will print 99.
}
But if you use "static" in a.m, then you will get build error, you will be told that "tryMe" could not be found. Because "static" make the variable local to the file which defines the var.
While, if you define a var as property, then the var is a member of the class, so each instance of the class has its own copy of the var.
I'm coming from C# development and just started to learn Objective-C and Xcode 4.
As far as I understand "#synthesize" is replacing getter/setter methods for properties if you don't need to check/control the values which are being read or written.
But why does Xcode 4 create a instance variable for me automatically?
Wouldn't this be enough:
#synthesize myProperty;
instead of:
#synthesize myProperty = _myProperty;
?
Why would I want to use/have the instance variable instead of the actual property if I don't have/need any getters or setters?
Thanks in advance!
MemphiZ
EDIT:
I understand that #synthesize is replacing getters/setters but what is this part good for: = _myProperty;?
Why would I want to have a instance variable if I could use "myProperty" directly? I would understand using "_myProperty" if the setter for example would check for a condition of the value. If I then want to skip this check I would use _myProperty. But as I use #synthesize I don't have a setter in place that does some check. So why do I have/want an instance variable then?
ANSWER:
See the comments in MattyG's post!
This is a convention used to remind the programmer to access the instance variables through the setters and getters with self. So if you're using:
#synthesize myProperty = _myProperty;
Then to access the variable directly you must write:
_myProperty = something;
To access the variable through it's setter you must write:
self.myProperty = something;
The benefit is that if you forget to access through self. then the compiler will warn you:
myProperty = something; //this won't compile
See this also this Question.
Well, you DECLARE a property's instance variable in the .h file, as well as the property itself. The interface to the property as well as the instance variable it'll use have been established with that... its implementation has not. That's where the #synthesize keyword comes in. It just implements the property for you, so that you don't have to write it out yourself.
Here are ways to declare properties in C#
private int _int1;
public int int1 {
get { return _int1; }
set { _int1 = value; }
}
This is a pretty common piece of code, and C# lets you abbreviate it to avoid having to type the same thing over and over
public int int1 { get; set; }
The difference between these two code segments is that the private variable "_int1" does not exist in the latter, since C# creates a variable internally. The #synthesize keyword is nice because it saves you the hassle of writing down the same code over and over while still allowing you to access the instance variable it's based on.
Edit. It's also important to note that getters and setters do exist in objective C. They just have different names than in C#, where they're labeled get{} and set{}. In objective C, the getter is a method with the same name as its instance variable, and the setter is a method with the word 'set' followed by the instance variable name with the first letter capitalized.
So, lets say you have this in your .h file
int myVar;
...
#property(nonatomic, assign) int myVar;
You can implement getters and setters yourself in the .m file
-(int)myVar {
return myVar;
}
-(void)setMyVar:(int)newVar {
myVar = newVar;
}
or you can just use #synthesize to have the getter and setter written automatically
I want to have a variable that I can access anywhere by importing a header file but I also want it to be static in the sense that there is only one of them created. In my .m file, I specify
static BOOL LogStuff = NO;
and in the initialize method I set the logging value:
+ (void)initialize
{
LogStuff = ... //whatever
}
However I want to be able to access my variable anywhere by importing the .h file so I want to do something like this:
static extern BOOL LogStuff;
but I'm not allowed to do that. Is it possible to do the thing I'm trying to do? Thanks
static in Objective-C means a different thing than static in a C++ class, in the context of static class data members and static class methods. In C and Objective-C, a static variable or function at global scope means that that symbol has internal linkage.
Internal linkage means that that symbol is local to the current translation unit, which is the current source file (.c or .m) being compiled and all of the header files that it recursively includes. That symbol cannot be referenced from a different translation unit, and you can have other symbols with internal linkage in other translation units with the same name.
So, if you have a header file declaring a variable as static, each source file that includes that header gets a separate global variable—all references to that variable within one source file will refer to the same variable, but references in different source files will refer to different variables.
If you want to have a single global variable, you can't have it in class scope like in C++. One option is to create a global variable with external linkage: declare the variable with the extern keyword in a header file, and then in one source file, define it at global scope without the extern keyword. Internal linkage and external linkage are mutually exclusive—you cannot have a variable declared as both extern and static.
An alternative, as Panos suggested, would be to use a class method instead of a variable. This keeps the functionality within the scope of the class, which makes more sense semantically, and you can also make it #private if you so desire. It does add a marginal performance penalty, but that's highly unlikely to be the bottleneck in your application (if you suspect it is, always profile first).
If LogStuff is a static class field, maybe you can implement static getter and setter?
+ (void)setLogStuff:(BOOL)aLogStuff;
+ (BOOL)logStuff;
Declare it extern BOOL in your header file. Files that #import your header don't know or care if the external symbol is static or not.
Separate global variable (one per source file):
// .h
static NSString * aStatic;
//.m
static NSString * aStatic = #"separate";
Unique global variable:
// .h
extern NSString * anExtern;
// .m
NSString * anExtern = #"global";
I normally use this layout for my statics:
NSMutableArray *macroArray;
BOOL keepMacro;
+ (void) startMacro
{
if (macroArray == nil)
{
macroArray = [[NSMutableArray alloc] initWithCapacity:100];
}
[macroArray removeAllObjects];
keepMacro = YES;
}
This is the startMacro command in my application. Both the Bool and the macroArray are static, but notice they are not declared static or extern.
This may not be the best practice, but this is what I do.
// in ClassA.h
static NSString *globalStr = #"HelloWorld";
#interface ClassA
...
#end
// in ClassB.h
#include "ClassA.h"
// in ClassB.m
...
NSLog(#"The global string: %#", globalStr);
...
In C++, "static" should mean the variable or function has a internal linkage.
But it is used to share the variable in this case, error will occur without the static keyword.
I'm confused, could someone tell me the concept behind?
Thanks!
static means exactly the same thing in Objective-C that in means in C - it has internal linkage and static storage duration. You get an error without the static in this case because you will have a duplicate symbol globalStr in each object whose source code included ClassA.h. You're not sharing anything - you're getting a new copy of globalStr for each compilation unit.
Don't put object definitions in your headers and you'll be better off. If you want a single global string, you need to put
extern NSString *globalStr;
In ClassA.h, and define it in exactly one implementation file as:
NSString *globalStr = #"HelloWorld";