I have an instance variable in my view controller that I would like to share with the whole program. I'm not quite sure how to do this. Can I just declare it as a static instance variable and then access it through properties like ViewControllerClass.instancevariable?
Thanks!
In reply to your comment attached to the question:
If you have an instance variable in Object X, any other object that has a reference to X can access that variable through the usual means:
[objectX myClassAInstanceVariable];
// Or, if declared with #property
objectX.myClassAInstanceVariable;
If the other object doesn't have a reference to X, then it can't access the variable, no matter the state or kind of the variable. In this case, you may want to rethink your design, or see my last paragraph below about the app delegate.
The concept of "static" is different in Objective-C than what you may be expecting (it sounds like you're coming from experience with Java).
Objective-C doesn't really have a concept of "class variables", although it is fairly easy to simulate such a thing; this is described in the question that mathk linked to: Objective-C Static Class Level variables. You declare a variable in the class's header file which is static, so that it is inaccessible outside that file, and create accessor class methods for it.
Any object that has a reference to your view controller can send messages to it. Note that in Objective-C, member variables are "protected" by default, meaning that only an instance of a class or subclasses, not other objects, can access those variables. Other objects must go through setter and getter methods.
Just as another option, because the background of your question is not clear, if you have some kind of a "global variable" which isn't really specific to your view controller, a better place to put it may be the application delegate*. Any object can get a reference to the delegate at any time:
[NSApp delegate];
NSApp is a global reference to the NSApplication object which is at the core of your program.
*Although it's certainly possible to overdo this.
Related
I'm new to Objective-C and was wondering if anyone could provide any information to clarify this for me. My (possibly wrong) understanding of object instantiation in other languages is that the object will get it's own copies of instance variables as well as instance methods, but I'm noticing that all the literature I've read thus far about Objective-C seems to indicate that the object only gets copies of instance variables, and that even when calling an instance method, program control reverts back to the original method defined inside the class itself. For example, this page from Apple's developer site shows program flow diagrams that suggest this:
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1
Also in Kochan's "Programming in Objective-C", 6th ed., pg. 41, referring to an example fraction class and object, the author states that:
"The first message sends the setNumerator: message to myFraction...control is then sent to the setNumerator: method you defined for your Fraction class...Objective-C...knows that it's the method from this class to use because it knows that myFraction is an object from the Fraction class"
On pg. 42, he continues:
"When you allocate a new object...enough space is reserved in memory to store the object's data, which includes space for its instance variables, plus a little more..."
All of this would seem to indicate to me that there is only ever one copy of any method, the original method defined within the class, and when calling an instance method, Objective-C simply passes control to that original copy and temporarily "wires it" to the called object's instance variables. I know I may not be using the right terminology, but is this correct? It seems logical as creating multiple copies of the same methods would be a waste of memory, but this is causing me to rethink my entire understanding of object instantiation. Any input would be greatly appreciated! Thank you.
Your reasoning is correct. The instance methods are shared by all instances of a class. The reason is, as you suspect, that doing it the other way would be a massive waste of memory.
The temporary wiring you speak of is that each method has an additional hidden parameter passed to it: a pointer to the calling object. Since that gives the method access to the calling object, then it can easily access all of the necessary instance variables and all is well. Note that any static variable exists in only a single instance as well and if you are not aware of that, unexpected things can happen. However, regular local variables are not shared and are recreated for each call of a method.
Apple's documention on the topic is very good so have a look for more info.
Just think of a method as a set of instructions. There is no reason to have a copy of the same method for each object. I think you may be mistaken about other languages as well. Methods are associated with the class, not individual objects.
Yes, your thinking is more or less right (although it's simpler than that: behind the scenes in most such languages methods don't need to be "wired" to anything, they just take an extra parameter for self and insert struct lookups before references to instance variables).
What might be confusing you is that not all languages work this way, in their implementations and semantically. Object-oriented languages are (very roughly) divided into two camps: class-based, like Objective-C; and prototype-based, like Javascript. In the second camp of languages, a method or procedure really is an object in its own right and can often be assigned directly to an object's instance variables as well - there are no classes to lookup methods from, only objects and other objects, all with the same first-class status (this is an oversimplification, good languages still allow for sharing and efficiency).
I have a situation where I'm keeping references to ivars which need to be persistent. In one object, I have an array of pointers to ivars in another object, which are used over the entire lifetime of the program. In other words, I'm not just passing a reference to retrieve a value -- I'm keeping the pointers around.
Is this a valid? Is it possible that the ivars might move? Are there cases where objects instantiated objects are moved around at runtime unbeknownst to the program? Or, do objects stay exactly where they are created. If the later is the case, is there any reason not to use references the way I am?
I'm using ARC.
Note: This probably wasn't a good way to design this to begin with, but... it's all done and working 99%! (except for a nasty crash which reboots the entire phone... )
Objects and their instance variables don't move once created. However, you also need to keep a strong reference to the object that holds the ivar. Otherwise, the object might be deallocated, leaving you with a dangling pointer.
Note that it is generally a very bad idea to have pointers to another object's insntance variables.
While there's no technical problem with accessing the ivars from outside (as rob stated) there's still the architectural design to consider: The approach you've taken breaks encapsulation. Additionally it is very uncommon for Objective-C.
So regarding maintainability of your code I would recommend to refactor the code. In Objective-C there's no friend declaration as in C++, so it's unusual to access ivars from outside the declaring class.
Let's say an object of class A wants to access the ivars of an object of class B persistently (in your example).
What you normally do is create a property (with the strong annotation, like #property (strong) ClassB *myBVar) in class A to reference an object of class B.
If you want to set or read B's properties you use the dot notation or call the getter/setter methods:
myBVar.name = #"Jim";
NSLog(#"Name:%#",myBVar.name);
[myBVar setName:#"Jim"];
NSLog(#"Name:%#",[myBVar name]);
You never call a ivar directly as it's implementation might change.
When using Objective-C properties can you stop creating instance variables altogether or do explicit instance variables (not the ones synthesized by the properties) still serve a purpose where properties would be inappropriate?
can you stop creating instance variables altogether
No, you can't (in a sense). What you can do is stop declaring them if you have properties. If you synthesize a property and you haven't declared the instvar, it will get declared for you, so you are creating an instance variable, just not explicitly.
do they still serve a purpose where properties would be inappropriate?
It used to be the advice to create properties for everything because having synthesized properties does almost all of the retains and releases for you. However, with ARC that reason for using properties to wrap the memory management has gone away. The advice now (for ARC) is, I believe, use properties to declare your external interface, but use direct instance variables where the variable is part of the object's internal state.
That's a good reason to adopt ARC: properties revert to their true purpose only of being part of the class's API and it's no longer necessary to use them as a hacky way to hide memory management work.
Edit
One more thing: you can now declare instance variables in the #implementation so there is now no need to leak any implementation details in the #interface. i.e.
#implementation MyClass
{
NSString* myString;
}
// method definitions
#end
And I'm pretty sure it works in categories too. - see comment below
I recommend declaring everything as properties and avoiding manual ivars altogether. There is no real upside to manually creating ivars. Declare public properties in your header #interface, declare private properties in a private class extension in your .m file.
To some of JeremyP's points, internal use of accessors still has significant value under ARC, even though memory management is no longer a significant concern. It ensures that KVO works properly, subclasses better, supports custom setters (particularly for things like NSTimer), supports custom getters (such as for lazy instantiation), etc. It is exceedingly error-prone to have a mix of accessors and ivars. It's far too easy to forget which you need to access in which way. Consistency is the hallmark of good ObjC.
If you absolutely must declare an ivar for some reason, then you should do it in the #implementation block as JeremyP notes.
UPDATE (Oct-2013):
Apple's guidance (From Programming with Objective-C: Encapsulating Data):
Most Properties Are Backed by Instance Variables
In general, you should use accessor methods or dot syntax for property access even if you’re accessing an object’s properties from within its own implementation, in which case you should use self:
...
The exception to this rule is when writing initialization, deallocation or custom accessor methods, as described later in this section.
This question was addressed before here
When you use synthesize the instance variables are handled and instantiated for you. If you're using Lion with the new version of XCode also take a look at the various properties in ARC in Transitioning to ARC
you can always access properties from outside. So if you want a variable only to be read from inside a class you still have to declare a iVar. Also accessing a public ivar with object->ivar is slightly faster than using a method-call.
I'm in the process of looking over some code in a large project, and I have noticed that in several of the classes, instance variables are created but no corresponding properties (#property) are created.
Is it "wrong" to create instance variables without properties? Doesn't this become a memory management issue?
I've actually never seen code like this before so I'm not sure what to think at this point.
Thanks in advance!
#properties are merely shorthand -- very convenient short-hand -- for code you can write yourself, no magic about it.
It may also be that the #properties are declared in the implementation file within a class extension and there is no publicly accessible API for directly manipulating the instance variables.
There's no reason that you have to use the Objective-C 2 style setters/getters to manage your instance variables - as long as the instance variable is released within the dealloc method (if indeed it's a alloced/inited object, etc.) then there's nothing to worry about.
Bear in mind that prior to Objective-C, such properties (and the whole #property/#synthesize syntax) simply didn't exist, so you had to create your own getters/setters if you deemed it necessary/convenient.
Not at all. Instance variables work fine, and are subject to the same memory management rules as anything else: retain it before saving it to the instance var, and make sure you release it when you don't need it anymore (typically in the dealloc).
Some history here might be helpful:
In the beginning, there were only instance variables. "Properties" existed only in an informal way, by convention, for objects outside your class to access "public" data that the class exposed. You'd write your own -(Foo *)foo and -(void)setFoo:(Foo *)f methods for each of these. Those often were like boilerplate code, trivially returning the ivar in the first case, and doing the right retain/release/set dance in the latter.
So Objective-C 2.0 came along and gave us the ability to declare properties with the language syntax, and even generate the accessors for us-- lots of time and boilerplate code was saved.
As time went on, some people began to think about all ivars as "properties", public or private. The public ones appear in the .h file as #properties, but you can also create a private interface to your object in the .m file that declare your "private" #properties, so you can use the accessors inside your class. This might or might not be overkill, depending on your philosophy to it, but this I think has to the situation you see now, where naked ivars look suspicious.
They shouldn't. Instance variables happily exist without any of the other machinery. Just get your retain/release right (in non-GC runtimes).
As you get more advanced, see #bbum's answer to this question:
Must every ivar be a property?
for some more varsity things to think about around the benefits of properties around KVO and subclassing.
Properties for instance variables aren't mandatory. In fact, prior to v2.0 of Objective-C, there was no such thing as properties -- you had to write your own accessors and mutators for instance variables (if you wanted to access them outside of the class). Properties can simplify memory management, but to be honest, memory management of ivars isn't that difficult, and it's not hard to handle yourself.
I understand that one version directly accesses the instance variable and the other calls it's accessor method.
If self.classVariable = sandwich;
&
If classVariable = sandwich;
do the same thing.
Can someone explain the point of the extra typing?
In Objective-C, self.property is property access, not direct instance variable access. It is syntatic sugar for [self property] or [self setProperty:], and thus has the semantics of a message. Modern Objective-C runtime can synthesize a backing instance variable (of the same name as the property), but you may back a property with an instance variable with a different name or none at all. In other words,
self.property = foo;
id bar = property
and
property = foo;
id bar = property;
are not at all the same thing.
It's generally a bad idea to mix direct and property access (with the exception that you should be accessing ivars directly in -init and -dealloc methods) because you will easily run afoul of memory management rules.
The extra typing is to protect the code from future changes, in case a variable is named (in scope) equal to the class member.
It is also considered good practice (in some circles) to include Self when referring to members in the class to be unambiguously clear where it comes from which in some ways helps quicken comprehension of the code.
For Objective-C specifically, there is another difference as noted here http://answers.oreilly.com/topic/1193-calling-self-object-rather-than-calling-the-object-directly-in-objective-c/
The SELF.X notation goes through the accessors generated by the #synthesize directive, whereas X directly bypasses them.
If you go through the accessor you can set breakpoints there. Handy sometimes. Also things like retain/copy properties won't work if you don't go through the accessor.