What Does the Text Inside Parentheses in @Interface and @Implementation Directives Mean

Parenthesis after UIViewController

I think this is what you are looking for:

Categories and Extensions

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/chapters/occategories.html

Question about .h @interface in objective-c

Just search for "Categories in Objective C"

Perfect beginner post with example here

Varieties of @interface declarations, some with parentheses

This is just a normal class interface, inheriting from NSObject, where you declare ivars, properties and methods

// in the .h file
@interface MyClass : NSObject
// ...
@end

The following two are categories, which allow you to add methods to a class. It is not a subclass however (do not declare a method with the same name, as you won't be able to access the original one). If you have a named category of the interface (like @interface MyClass (Private)), then the implementation should be provided in @implementation MyClass (Private), in the case of unnamed categories (also called extensions), the implementation can be provided as usual. Note that extensions also allow you to add ivars to the class while (named) categories do not.

// in the .m file (what's the purpose of the parens?)
@interface MyClass ()
// more property declarations which seem like they can go in the .h file
@end

// again in the .m file (what's the purpose of private?)
@interface MyClass (Private)
// some method declarations
@end

What does this mean in Objective-C

The first implementation is just a new class. The second implementation is basically extension methods to an existing class, known as Categories. See the article: Categories and Extensions for more information.

As summarized at the top of the link:

A category allows you to add methods to an existing class—even to one for which you do not have the source. Categories are a powerful feature that allows you to extend the functionality of existing classes without subclassing. Using categories, you can also distribute the implementation of your own classes among several files. Class extensions are similar, but allow additional required APIs to be declared for a class in locations other than within the primary class @interface block.

What do the double parenthesis mean?

It's to do with the precedence of operations.

If you look here , you can see that dot notation has a higher precedence than casting.

So this code:

(TypeSelectionViewController *)nextViewController.recipe

would be converted by the compiler to the following (since dot . notation is just syntactic sugar for the compiler):

(TypeSelectionViewController *)[nextViewController recipe]

However, we wanted to cast the nextViewController part to type TypeSelectionViewController *, and not the [nextViewController recipe] part. So this is incorrect.

So instead we write this:

((TypeSelectionViewController *)nextViewController).recipe 

which the compiler converts to this:

[(TypeSelectionViewController *)nextViewController recipe]

which is what we want.

Note on compiler versus runtime behaviour

If you compile this example of incorrect casting:

UILabel *label = [[UILabel alloc] init];
NSString *result = (UILabel *)label.text;

You will get a message like this from the compiler:

Warning: incompatible pointer types initializing 'NSString *' with an 
expression of type 'UILabel *'

However, the code will work fine at runtime due to Objective C's weak typing. You can read more about this at the LLVM docs, e.g.:

The validity of conversions between object pointer types is not
checked at runtime.

Interface syntax with + sign (UIView+AdditionalFeatures.h)?

The naming convention you are observing is what is typically done with Objective-C categories.

It is convention, though not an explicit requirement of categories to name the file with the name of the class the category is being applied to, and then the +, followed by the name of the category itself.

Notice that the + is not added to the actual @interface of the category, it is merely in the file name.

Objective-C - Interface declaration syntax

I'm expanding @Siriss answer,

When you want to make a category for another class, you've to write it like this. I've not idea of Cocos3D, so I guess CC3OpenGL is a class in Cocos3D and you want to make a category for that class and named it, TemplateMethods.

Lets take an example,

@interface UILabel (OtherMethods)
// Methods declarations
- (CGSize) getLabelSize;
@end

Here, we make a category of UILabel and named it OtherMethods. We can #import it like, #import "UILabel+OtherMethods.hto access methods of it.

So, now you will have a method of UILabel and you can access it like the same way you access to the other methods of the UILabel.

UILabel *lbl = [UILabel new];
lbl.frame = CGRectMake:(10,10,300,100);
[lbl setTextAlignment:NSTextAlignmentRight]; //normal method
[self.view addSubview:lbl];
CGSize lblSize = [lbl getLabelSize]; //category method

To read more about it, read documentation here.

Confusion with header and Implementation files in Objective-C

I'll answer your questions below, but perhaps the best way to learn this stuff is to read some user-friendly notes intended for folks new to the language, such as the Learn Objective-C tutorial over at cocoadevcentral.

An example

I'd like to help answer your questions with an example (I love learning by example). Let's say you're a teacher writing a program that asks students a particular yes/no question, and keeps track of how many get it correct and how many students it has asked.

Here is a possible interface for this class:

@interface Question : NSObject {
NSString* questionStr;
int numTimesAsked;
int numCorrectAnswers;
}

@property (nonatomic, retain) NSString* questionStr;
@property (nonatomic, readonly) int numTimesAsked;
@property (nonatomic) int numCorrectAnswers;
@property (nonatomic) int numWrongAnswers;

- addAnswerWithTruthValue: (BOOL) isCorrect;
@end

The three variables inside the braces are instance variables, and every instance of your class will have its own values for each of those variables. Everything outside the braces but before @end is a declaration of a method (including the @property declarations).

(Side note: for many objects, it's useful to have retain properties, since you want to avoid the overhead of copying the object, and make sure it isn't released while you're using it. It's legal to retain an NSString as in this example, but it is often considered good practice to use copy instead of retain since an NSString* might actually point to an NSMutableString object, which may later change when your code expects it to stay the same.)

What @property does

When you declare a @property, you're doing two things:

  1. Declaring a setter and getter method in the class's interface, and
  2. Indicating how the setter and getter behave.

For the first one, it's enough to know that this line:

@property (nonatomic, retain) NSString* questionStr;

is basically the same as this:

- (NSString*) questionStr;                           // getter
- (void) setQuestionStr: (NSString) newQuestionStr; // setter

in the header. You literally are declaring those two methods; you can call them directly, or use the dot notation as a shortcut to call them for you.

The "basically" part in "basically the same" is the extra info given by keywords like nonatomic and retain.

The nonatomic keyword indicates that they're not necessarily thread-safe. The common retain keyword indicates that the object retains any value that's set, and releases previous values as they're let go.

For example:

// The correct answer to both questions is objectively YES.
Question* myQuestion = [[Question alloc] init];
NSString* question1 = [[NSString alloc] initWithString:@"Is pizza tasty?"];
// question1 has retain count of 1, from the call to alloc
myQuestion.questionStr = question1;
// question1 now has a retain count of 2
NSString* question2 = [[NSString alloc] initWithString:@"Free iPhone?"];
myQuestion.questionStr = question2;
// question1 has a retain count of 1, and question2 has retain count of 2

If the @property declaration for questionStr had been assign instead, then all the myQuestion.questionStr = statements would not have made any changes at all to the retain counts.

You can read a little more about properties here.

What IBOutlet and IBAction do

These are basically no-op words which act only as a way to tell Interface Builder which pieces of the header file to pay attention to. IBOutlet literally becomes an empty string when the compiler looks at it, and IBAction becomes the void return value. We do need them to work with Interface Builder, though, so they are important -- just not to the compiler.

Quick note on C structs and arrow vs dot notation

By the way, the data part of an Objective-C object is very similar to a C struct. If you have a pointer to a C struct, you can use arrow notation -> to refer to a specific part of the struct, like this:

struct MyStructType {
int i;
BOOL b;
};
struct MyStructType* myStruct;
myStruct->i = 3;
myStruct->b = TRUE; // or YES in Objective-C.

This same syntax works the same way in Objective-C:

Question* question = [[Question alloc] init];
question->questionStr = @"Is this a long answer?"; // YES

But when you do this, there is no method call happening behind the scenes, unlike the dot notation. With the dot notation, you're calling the setter (or getter if there's no = afterwards), and these two lines are the same:

question.questionStr = @"Chocolate?";
[question setQuestionStr:@"Chocolate?"];

It's often a good idea to avoid the arrow notation in favor of the dot notation, since the dot notation lets you enforce valid state -- for example, that the pointers your class has are always retained. You can even disallow others from using the arrow notation by declaring your instance variables as @private; they can still use the getter and setter to access it, if you declare a @property for it.

What @synthesize does

Now, when you get around to actually implementing your class, @synthesize says something like "make sure the getter and setter get implemented for this property." It does not say "implement both of these for me," because the compiler is polite enough to check for your own implementation first, and only fill in the pieces you've missed. You don't have to use @synthesize at all, even if you use @property out the wazoo -- you could always just provide your implementations for your setters and getters, if you're into that sort of thing.

You probably noticed in the Question interface above that there's a property which is not an instance variable (numWrongAnswers), which is fine because you're just declaring methods. In the example code here, you can see how this actually works:

@implementation Question

@synthesize questionStr, numTimesAsked, numCorrectAnswers;

- (void) setNumCorrectAnswers: (int) newCorrectAnswers {
// We assume the # increases, and represents new answers.
int numNew = newCorrectAnswers - numCorrectAnswers;
numTimesAsked += numNew;
numCorrectAnswers = newCorrectAnswers;
}

- (int) numWrongAnswers {
return numTimesAsked - numCorrectAnswers;
}

- (void) setNumWrongAnswers: (int) newWrongAnswers {
int numNew = newWrongAnswers - self.numWrongAnswers;
numTimesAsked += numNew;
}

- (void) addAnswerWithTruthValue: (BOOL) isCorrect {
if (isCorrect) {
self.numCorrectAnswers++;
} else {
self.numWrongAnswers++;
}
}

@end

One thing that's happening here is we're faking an instance variable called numWrongAnswers, which would be redundant information if we stored it in the class. Since we know numWrongAnswers + numCorrectAnswers = numTimesAsked at all times, we only need to store any two of these three data points, and we can always think in terms of the other one by using the two values we do know. The point here is to understand that a @property declaration is really just about declaring a setter and getter method, which usually corresponds to an actual instance variable -- but not always. The @synthesize keyword by default does correspond to an actual instance variable, so that it's easy for the compiler to fill in the implementation for you.

Reasons to have separate .h and .m files

By the way, the whole point of declaring methods in one file (the .h header file) and defining their implementation in another (the .m or methods file) is to help decouple the code. For example, if you only update one .m file in your project, you don't have to recompile the other .m files, since their object code will remain the same -- this saves time. Another advantage is that you can use a library that includes only header files and pre-compiled object code, or even dynamic libraries where you need the header file so the compiler is aware of which methods exist, but those methods aren't even linked in with your executable file. These advantages are hard to appreciate when you first start coding, but just the logical breakdown and encapsulation of implementation becomes useful after a short while.

I hope that's helpful!



Related Topics



Leave a reply



Submit