A Quick Objective-C 2.0 Tutorial: Part II

NSString * movieTitle = movie.title;

NSString * director;

director = movie.director.fullName.capitalizedString;

NSUInteger movieTitleLength;

movieTitleLength = movie.title.length;

NSString * director;

director = [[ [movie director ] fullName ] capitalizedString ] ;

NSUInteger movieTitleLength;

movieTitleLength = [[movie title ] length ];

@interface NSString (MyCategory)

- ( NSUInteger ) lengthWithoutSpaces ;

@end

NSUInteger movieTitleLength;

movieTitleLength = movie.title.lengthWithoutSpaces;



@interface Movie : NSObject

{

NSString * summary;

}

- ( NSString *) summary ;

@end



@interface Movie (Private)

- ( void ) setSummary : ( NSString *) aValue ;

@end



@implementation Movie

- ( void ) setSummary : ( NSString *) aValue

{

NSString * oldSummary = summary;

summary = [aValue retain ] ;

[oldSummary release];

}

@end



@interface Movie : NSObject {

NSString * summary;

}

@property (readonly) NSString * summary;

@end

@interface Movie (Private)

@property (readwrite,copy) NSString * summary;

@end



@implementation Movie

@synthesize summary;

@end

-[Movie setSummary:]: unrecognized selector sent to instance 0x132ac0

readonly

readwrite

@interface Movie ()

@property (readwrite,copy) NSString * summary;

@end



warning: property 'summary' attribute in 'Movie' class continuation

does not match class 'Movie' property

@interface Movie : NSObject {

NSString * summary;

}

@property (readonly) NSString * summary;

@end

@interface Movie ()

@property (readwrite,copy) NSString * summary;

@end

assign

@property (readonly,assign) NSString * summary;

@property (readwrite,copy) NSString * summary;



copy

@interface Movie : NSObject {

NSString * summary;

}

@property (readonly,copy) NSString * summary;

@end

@interface Movie ()

@property (readwrite,copy) NSString * summary;

@end

error: object cannot be set - either readonly

property or no setter found

Movie

self .summary = @"Superheroing meets everyday life." ;

@property (assign,getter=isSelected) BOOL selected;

@property (copy,setter=setDefaultTitle:) NSString * title;

@synthesize propertyName=ivar;

@interface Movie : NSObject {

NSString * movieTitle;

}

@property (copy) NSString * title;

@end

@implementation Movie

@synthesize title=movieTitle;

@end

@synthesize

@implementation Movie



@synthesize title;



- ( void ) setTitle : ( NSString *) newTitle {

title = [newTitle copy ] ;

}



@end

@synthesize

NSManagedObject

@dynamic

@synthesize

@interface Movie : NSManagedObject {

}

@property (retain) NSString * title;

@end

@implementation Movie

@dynamic title;

@end

title

NSManagedObject

@dynamic

@dynamic

poseAsClass:

/usr/include/objc/runtime.h

NSString * fileName = filePath.lastPathComponent;

NSSize imageSize = image.size;

person.fullName = @"Bob Parr" ;



container.rebuildCache;

fileName.stripWhitespace;

object.alloc.init;

A Quick Objective-C 2.0 Tutorial: Part II

Posted Nov 3, 2007 — 30 comments below Posted Nov 3, 2007 — 30 comments below

In the first tutorial , we looked at the basic syntax and features in Objective-C 2.0. In this installment, we'll take a look at some of the options for customizing, and some of the more advanced syntax.This may be obvious, but a few comments I've seen elsewhere suggests maybe it's not. If you use dot syntax like this:You can continue to add dots to the expression:Which is equivalent to:If you have a category for an existing class, you can use it with dot syntax as you would any other property:This syntax should only be used for methods that act as getters or setters.Some properties should have public getters andsetters. A good example of this is a cached value that you don't want clients to set directly. The conventional Cocoa solution to this is to create a Private category:If you translate this to the property syntax, you'll end up with the following:This looks okay, but when the program runs, we see that the setter was never actually implemented:The reason for this is that the compiler only looks at theclass definition — not additions from categories — to determine which methods to implement. Summary is declared as, so the compiler doesn't generate a setter.But there's another way. Objective-C 2.0 allows you to create nameless categories, which are formally called. From the compiler's perspective, any methods in a continuation are part of the original class — not just add-ons. This gives the compiler enough information to generate a setter.Using a class continuation, we can redefine the property privately in the implementation file to beThe one caveat here is that we get a warning:Let's put the two definitions side-by-side to see why we get this warning:If we don't specify copy/retain/assign, the property defaults to. So, to the compiler, it looks like this:We can fix this by changing theproperty definition to. Here's the final, correct version of a public property with a private setter:It looks a little bit weird, but usually it's better to make sure your project compiles without warnings. And don't worry about clients of your class accidentally calling the setter. If they do, they'll get this:That's a hard, not a warning. If theclass attempts to set its own private value internally, no errors or warnings are generated:If you want customize getter and/or setter names, it's a simple matter of adding an additional key/value pair to the property declaration:The setter is a bit different. It must have the colon at the end to match normal Objective-C notation:You should use these sparingly, though. Properly-named accessors will make your life easier, particular with Key-Value Coding and Cocoa Bindings. The example above of adding an "is" prefix is fairly common for BOOLs, and Key-Value Coding is smart enough to understand the intention.You can also override instance variable names. By default, the compiler will look for an instance variable which has the same name as the property, but you can customize this with the following syntax:For example:Thedirective is flexible. It will only generate accessors for methods which don't already exists. For example, this is completely valid:In this case,will only generate a getter, since the setter already exists. This is helpful if you want to do something other than just set a value in the setter — such as add logging, for example.Some accessors are created dynamically at runtime, such as certain ones used in CoreData'sclass. If you want to declare and use properties for these cases, but want to avoid warnings about methods missing at compile time, you can use thedirective instead of. For example:The other subtle note here is that there's noinstance variable defined. This is becausehas its own data store. Since we're using, there will be no warnings or errors about the missing instance variable.Using thedirective essentially tells the compiler "Themethod has been deprecated, but the runtime functions have been completely overhauled, so you might be able to find what you need inIn terms of style, you should only use the dot syntax for things that act as getters and setters. You should not use it for utility methods, for example. In this way, Objective-C is different from Ruby, JavaScript, Java, and so on:Finally, it's worth noting that Xcode 3.0 can actually convert your code to Objective-C 2.0: