|
As you know, a model object is a simple object that represents state. It is really not much more than a container for data. Business logic often gets stuffed into model objects to make sure that you cannot store an invalid state on that object, but by and large we're looking at property buckets.
When building a model object in C# that is going to be bound to a UI, typically we do the following things:
public class Customer : ModelObject
{
private int age;
private string firstName;
private string lastName;
public int Age
{
get
{
return age;
}
set
{
NotifyPropertyChanging("Age");
age = value;
NotifyPropertyChanged("Age");
}
}
// Implementations of properties for firstname and lastname
}
So what does this look like if you're trying to build a model object that will be bound to UI within Cocoa? Thankfully, it's actually a little simpler. Key-Value-Observing is something that is built right into everything from the ground up, so when you synthesize properties you don't actually have to manually let other objects know about when properties are changing and when they've finished changing - that's all automatic. Here's what the same class looks like in Cocoa:
(Customer.h):
#import <Cocoa/Cocoa.h>
@interface Customer : NSObject {
@private
NSString *_firstName;
NSString *_lastName;
NSInteger _age;
}
@property (nonatomic, retain) NSString *firstName;
@property (nonatomic, retain) NSString *lastName;
@property (nonatomic, assign) NSInteger age;
@end
(Customer.m):
#import "Customer.h"
@implementation Customer
@synthesize firstName = _firstName;
@synthesize lastName = _lastName;
@synthesize age = _age;
@end
There's a couple of things that .NET developers need to watch out for when looking at Cocoa documentation. One is that there are a LOT of websites out there that have REALLY OLD code samples. Do not let yourself get lured into not taking full advantage of Objective-C 2.0 unless you plan on building for Tiger or earlier. First you'll see the @private directive. This should make perfect sense - the items declared below this directive are, as should be obvious, private. This is not what a lot of old Cocoa documentation would lead you to believe. Do not believe people when they tell you that all Objective-C member variables are public. That's old school crap and, as a C# programmer, you are more likely to feel comfortable having a very clear separation between your private member variables and your public properties.
What you see next are the @synthesize statements. These will actually build the get/set accessors for you. They are somewhat similar to C# 3.5's automatic property syntax, but not quite. The difference? C# 3.5's automatic properties won't fire INotifyPropertyChanged or INotifyPropertyChanging events for you, but Objective-C synthesized member accessors are KVO-compliant and will notify the GUI when relevant changes occur, automatically.
Anyway, I thought some of you .NET developers looking into Cocoa for whatever *iPhone* reason *iPhone* might find this little comparison useful.
Look for more blog posts along a similar vein that will hopefully start bridging the gap between the .NET and Cocoa worlds and make the transition smooth and easy.
Kevin, Can you recommend a really good book for a proficient C# developer
who wants to break into Cocoa?
As always, I would say the single best introduction to Cocoa/Objective-C
programming book is Aaron Hillegass' book: Cocoa Programming for Mac OS X..
Just make sure you get the third edition, which now includes coverage of
garbage collection and Core Data.
Small critique: I can't recall anyone ever recommending that all or even
any Objective-C instance variables should be public. My use of Objective-C
goes back 20 years. Many Objective-C programmers will recommend using the
default @protected access control for instance variables.
I suggest that you use the "copy" attribute instead of "retain" when
declaring NSString properties. A -copy message works just like a -retain on
an immutable NSString, but it will actually make a copy of an
NSMutableString, which is typically what you want. You don't want to store
a pointer to an object whose contents could be changing behind your back.
As a beginner I got a small question: Why is NSString a pointer, but
NSString not?
@Jens K: NSString is an object, but NSInteger is just a regular data type.
It was introduced to use instead of a regular int so that you can write 32
and 64 bit compliant code.