Objective-C : Object declaration question - objective-c

there is something I try to understand. I have this object declaration in my AppsController-Class for a Cocoa Application
NSMutableArray *personArray;
In can put this declaration inside the Header file or inside the implementation of the class in the code file. It makes no difference. I can even put it outside the #implementation context right under the #import commands.The Application works just fine.
Since I don't inherit from the AppsController Class or do anything else fancy with it I wonder what might be the difference between these types of declarations?
Where does the declaration really belong?

It depends on how you want to use the variable. If you place the variable declaration inside the interface for your class, each instance of your class will have its own copy of the variable, which is kept separate from all other instances of your class:
#interface AppsController : NSObject
{
NSMutableArray *personArray;
}
Each instance of the AppsController class will have its own copy of the personArray variable, which is separate from all other instances of the class.
If, however, you define the variable outside of the interface, it becomes a global variable, and it is a shared (instances of your class do not get their own copy), and can be accessed from any instance of your class. If you declare it in the header as such:
NSMutableArray *personArray;
it is also visible to methods in other files and classes that include your header.
If you declare the variable in the implementation file, but outside of the implementation itself, and prefix it with the static keyword, the variable will only be visible to the implementation of your class. This is common when you want a variable that is visible to you all of class instances, but not visible to anyone else, and is a way to create class variables.
Since your object is a controller object, I am guessing that you only have one instance of it present in your application. You should declare the variable either:
As an instance variable if your personArray variable needs to be unique to each instance of your controller class (even if you only have one instance now, you may have more than one instance of it in future).
As a class variable (using the static keyword) if you want the variable to be visible to all instances of your class, with only one, shared instance of the variable.
As a global variable if you want the variable to be a single instance (not unique to instances of your class) and also visible to other classes or code in other files.

You should probably put it in the interface section of the header file, that way there will be one instance of it per object instantiated. Which I presume is your intention.
I think if you put it elsewhere it will be treated as a global variable. Ie, there will only ever be one instance of personArray, and it will be visible from anywhere in your application.
Your application is probably working fine, because you only have one instance of your AppsController Class, and no other variables called personArray. If you ever need a second AppsController, or another variable elsewhere called personArray, you'll run into problems.

If you declare the variable in the implementation file, but outside of the implementation itself, and prefix it with the static keyword, the variable will only be visible to the implementation of your class. This is common when you want a variable that is visible to you all of class instances, but not visible to anyone else, and is a way to create class variables.
just to clarify, the reason variables declared inside the implementation file but outside the implementation section are not available outside the class, is because other classes are not aware of anything inside the implementation file. your import statements refer to headers, not their implementations, so they know nothing of those implementation file declarations.
anyway, to create a static variable accessible only by a class, use keyword static when making a declaration in an implementation file. you can put it at the top of the file, at the top of the implementation section, or inside a function, depending on what you want the scope to be.
edited: corrected, thanks peter

Related

Why I can't access this property in class?

Please refer to this image, I have declared property matchResult, why couldn't I access it from its instance?
The other property "score" works, why?
The code runs in iOS6 environment.
Please open image in a new tab if you couldn't see it clearly.
Thanks
It seems that you have defined the property in the implementation file "CardMatchingGame.m",
using a class extension. That means that the property is only available in the #implementation block of this class.
To make the property accessible from other classes, move the declaration to the public #interface in "CardMatchingGame.h".
It is declared within the .m file and therefore not visible from "external". It does not matter that you access it from a method of the same class. You acces an external interface by referring to self.game.matchResult.
If game equals self then you could access self.matchResult. But I do not think it does because you fetch self.game from the array self.cardButtons.
So, you will either use self.matchResult if you are referring to self or you will have to move the property to the interface definition within the .m file.

Where would I place a global utility function in Objective C?

When writing an iOS app, where would I place a function that I intend to use from any other file?
For example, a function to convert a NSDate to a relative time string ("5 secs ago").
Would I make a class and make these functions all static?
Functions can be placed wherever convenient. If a function or group of functions is likely to be imported in many places, you can declare and implement them in their own .h/.m pair. So for example you might implement your date conversion function in a file named XYZDateUtilities.m, and declare it in XYZDateUtilities.h.
Declaring functions with the static qualifier would limit their scope to the file in which they were declared, so you wouldn't want to do that; in fact you'd want to do the opposite -- declare them as extern in the .h file so that they'll be visible in other files.
You have a couple options:
1) If you're extending the behavior of a class (such as the NSDate string conversion method you described), it may work best to simply create a category on said class.
Here's a tutorial on iOS categories:
http://mobile.tutsplus.com/tutorials/iphone/objective-c-categories/
Important Note:
Categories change a class's behavior (if you override a method) everywhere within the project whether or not you include the header (.h) file in another specific class's imports
For this reason, it's generally best to not override methods via a category, but instead, to create a subclass if you want to change certain methods.
For adding new methods, however, categories can be very convenient and useful.
2) If you want to create a new class that's imported everywhere, you can create said class and put its header import, i.e. #import "MyClass.h", into your project's prefix.pch file (found under the "supporting files" group within the project by default).
Anything that you put into the prefix.pch file will be available anywhere within your app. This is also a useful place to put constants (such as strings) or define enums that are used across many classes within the app.
I hope this helps. Let me know if further clarification is needed, and I'll do my best to help.
Cheers!
Another option would be to create a class for your helper methods and implement all the helpers as class methods.
e.g. HelperClass.h
+ (NSString *)getFrenchCapital
e.g. HelperClass.m
+ (NSString *)getFrenchCapital
{
return #"Paris";
}
Then import your helper class wherever you need it, and simply call the class methods:
e.g. Foo.m
#import "HelperClass.h"
...
- (void)logFrenchCapital
{
NSLog(#"Capital of France: %#", [HelperClass getFrenchCapital]);
}
If you make all functions static in a class, then alternative is to just define functions in .m file, and extern functions in .h file, just like what you do in C.

How to define methods and properties only visible within an objective-c framework?

I am trying to write an objective-c framework and I would like to have methods and properties visible only within the framework. I know I could define them in a class extension inside the implementation file but then they will not be accessible by other classes.
One way I was thinking to do it was to define a category for example MyClass+Internals and make that header private. but make the MyClass.h header public. I was wondering if there was a better way of doing this. Also, I'm not sure you can define properties within a category I thought it was only methods. Thanks for any suggestions or feedback.
Say you have a class named "Foo", then in "Foo_Framework.h", create:
#interface Foo()
#property ....;
- .... method ....
#end
Then, make sure that "Foo_Framework.h" is imported before the #implementation Foo. That'll cause the class Foo to be compiled with the extended interface found in said header file. That header can then be used throughout your framework. Just don't make it available outside said framework.
You are correct that you can't declare properties (that are synthesized) in a category. That was one of the primary motivations for the creation of class extensions, of which the above is an example.

Global variables in Objective-C - difference in extern and top of .m file declaration

I know you can define a global variable in Objective-C by using "extern", but I just realized that the variables I had declared at the top of my .m file before my first method were also accidentally global (and that was causing some problems). I moved them into the #interface part of my header file, which I think correctly declares them as only existing within the class, which has solved some of my problems, but I am still a bit confused.
What is the difference in declaring a variable as extern and putting it at the top of a .m file? Or do those result in the same thing?
extern is a way of explicitly stating, for readability and compile-time enforcement, that you are just declaring this variable here, and actually expect it to be defined elsewhere. If you were to also try to define the extern variable the compiler will tell you the error of your ways. This is useful for global variables to prevent name collision and multiple definitions, both of which will get you linker errors. The extern keyword itself, however, does not make the variable global.
What does make the variable global is the position of its declaration in the file. If you were to declare a variable outside the #interface in a class' header file, you would have declared a variable that is shared across and visible to all instances of your class, as well as anyone who #imports the header. If you were to (and apparently did) declare a variable outside of the #implementation in your class' .m file, you would have also have declared a variable that is shared between all instances of your class, but is not visible to anyone who #imports you header.
So, use the position of variable declarations to determine scope. You will only define these global variables in one place. For all other places that you declare them, prefix the declaration with extern to make the code readable, your intentions clear, and to make sure you don't also try and define it again.

Private interface vs. private method - objective c

What is the difference between a private method and a private interface?
For example, I know that if you define a method in an implementation and its interface does not mention it, it is considered a private method. I have also seen things such as:
#interface Collector()
#property (readonly) NSMutableDictionary *count;
#end
Inside of the .m implementation file.
#interface Foo() creates a class extension (I stand corrected, props to bbum) on interface Foo which is like additional methods added to the interface. Some people also use #interafce Foo(Private) (category) instead of a class extension with (). It's more like "injecting" new methods into a class from outside the class.
Placing this in the .m file just keeps other things from "seeing it" in the .h file, but that's it. Basically people normally use categories or class extensions in .m files to specify private interfaces, but they are also used for things like UIKit uses categories to add row and section public methods to NSIndexPath. (This can be confusing.)
You don't really need to define private methods this way, but if you have a method called bar that calls method foo before foo is defined in the source file you'll get a compiler warning something like "object self may not respond to foo". You can get rid of that by defining foo before you define bar or any other foo-calling code. It's the same with plain C and functions.
Like Ole says this doesn't stop anyone from calling the private methods, it just declares your intention that they be private and causes the compiler to generate the "may not respond to" warnings even if they import the .h file.
EDIT
Also see http://www.friday.com/bbum/2009/09/11/class-extensions-explained/ for some explanation of categories vs. class extensions. Looks like class extensions should be more correct for defining private methods, from a compiler warning perspective, because category methods are optional. Wish my book would have explained this!
Objective-C has no totally private methods. The method declared in a private interface section in the .m file is invisible to outside callers but it is not private. If someone knows the method signature and ignores the compiler warning, they can call it from outside without problems.