Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

CaptSaltyJack

macrumors 6502
Original poster
Jun 28, 2007
351
1
I just learned about @property and @synthesize. Cool stuff. But I'm a little confused on a few things as far as how to implement my class.

Is this code correct/ideal?

Code:
@interface Person : NSObject {
  NSString *firstName;
  NSString *lastName;
  int age;
}
@property (readwrite, copy) NSString *firstName;
@property (readwrite, copy) NSString *lastName;
@property (readwrite, assign) int age;

@end

First question: should age be an int? Or NSNumber? Or NSNumber*? Or NSInteger or NSInteger*? I'm confused about whether NSNumber should be a pointer or not.. after all, it IS an object, and with most of these objects, they're pointers.

Second: is it pretty much a given that the @property option "copy" will be used for NSString* all the time? And "assign" is used for ints and other non-pointers, and "retain" is used for pointers to objects other than NSString? I'm not clear on when to use each one.
 

HiRez

macrumors 603
Jan 6, 2004
6,265
2,630
Western US
That looks fine. It's up to you whether to represent numbers with primitives or NSNumber objects (I don't think there is an NSInteger object class). It's very common to use ints and floats instead of NSNumbers. However, bear in mind that you can only store objects in the collection classes (NSArray, etc.), so if you do that you might find yourself wrapping and unwrapping primitive values to NSNumber anyway, and NSNumbers also work natively with file archiving.

I might also suggest storing "age" as an NSDate containing the person's birthday as well, then you can always derive age from that.

As for copy vs. retain for strings it's up to you but generally strings are copied (unless they are potentially huge because strings can be very large). Copy is a bit safer IMO, then at least you know you own it completely. NSNumbers I would copy as well.
 

CaptSaltyJack

macrumors 6502
Original poster
Jun 28, 2007
351
1
That looks fine. It's up to you whether to represent numbers with primitives or NSNumber objects (I don't think there is an NSInteger object class). It's very common to use ints and floats instead of NSNumbers. However, bear in mind that you can only store objects in the collection classes (NSArray, etc.), so if you do that you might find yourself wrapping and unwrapping primitive values to NSNumber anyway, and NSNumbers also work natively with file archiving.

I might also suggest storing "age" as an NSDate containing the person's birthday as well, then you can always derive age from that.

As for copy vs. retain for strings it's up to you but generally strings are copied (unless they are potentially huge because strings can be very large). Copy is a bit safer IMO, then at least you know you own it completely. NSNumbers I would copy as well.

You would copy vars of type NSNumber, or NSNumber* ? (or both?)

BTW:

Go outside, the graphics are amazing!

best sig ever :)
 

Krevnik

macrumors 601
Sep 8, 2003
4,101
1,312
You would copy vars of type NSNumber, or NSNumber* ? (or both?)

NSNumber is an object, so you always use it as (NSNumber *).

NSInteger/NSUInteger is a scalar value, so you don't need to represent it with a pointer.

NSNumber allows for 'boxing' values into an object that can be put into NSArrays and the like. It really isn't meant for regular use (performance issues compared to simply using the scalar value in RAM).

NSInteger and NSUInteger is meant to 'mask' the int and long types. NSInteger is guaranteed to be an integer of the same bit-width of the CPU you are running on. NSUInteger is the same, just unsigned. The Cocoa APIs in 10.5 moved to using these definitions so that a 64-bit app doesn't need to be tweaked to compile without any errors or warnings as long as you use these built-in types.
 

CaptSaltyJack

macrumors 6502
Original poster
Jun 28, 2007
351
1
NSNumber is an object, so you always use it as (NSNumber *).

NSInteger/NSUInteger is a scalar value, so you don't need to represent it with a pointer.

NSNumber allows for 'boxing' values into an object that can be put into NSArrays and the like. It really isn't meant for regular use (performance issues compared to simply using the scalar value in RAM).

NSInteger and NSUInteger is meant to 'mask' the int and long types. NSInteger is guaranteed to be an integer of the same bit-width of the CPU you are running on. NSUInteger is the same, just unsigned. The Cocoa APIs in 10.5 moved to using these definitions so that a 64-bit app doesn't need to be tweaked to compile without any errors or warnings as long as you use these built-in types.

So if I understand this correctly, I really should be using NSInteger instead of int, correct? Just to be on the safe side? Are there other scalar vars like NSFloat? Or can I just use float?
 

Krevnik

macrumors 601
Sep 8, 2003
4,101
1,312
Well, yes, actually, but they don't serve the same purpose. :)

There are a series of int types based on size:
NSInt8, NSInt16, NSInt32, and NSInt64, as well as unsigned varieties.

There is also NSFloat and NSDouble for the single and double-precision floating point.

You don't have to use them, as NSFloat is really just float, and NSDouble is really just double, NSInt8 being char and so on

I like the NSInt<size> ones because it tells me what size the variable is very quickly (and thus its limits). char, short, int, long, long long, etc are a little harder to decipher. For awhile I assumed int would be 64-bit on a 64-bit system, when really long is 64-bit on a 64-bit system.

NSUInteger and NSInteger are there more for the API's sake, and so anything I expect to pass around to the Cocoa API is one of these two, as well as anything where I don't care what the size is. If size is important, I use the NSInt<size> types for ease of reading.
 

CaptSaltyJack

macrumors 6502
Original poster
Jun 28, 2007
351
1
Roger. Thanks Krevnik!

Back to @property..could someone verify that my assumptions below are correct?

@property (assign) is the same as:

Code:
- (int)whatever
{
  return classVar;
}

- (void)setWhatever:(int)x
{
  classVar = x;
}

@property (retain) is the same as:

Code:
- (void)setWhatever:(NSObject *)o
{
  [o retain];
  [classVar release];
  classVar = o;
}

- (NSObject *)whatever
{
  [classVar autorelease];
  return classVar;
}

And lastly, @property (copy) is the same as:

Code:
- (void)setWhatever:(NSObject *)o
{
  classVar = [o copy];
}

- (NSObject *)whatever
{
  return classVar;
}
 

lee1210

macrumors 68040
Jan 10, 2005
3,182
3
Dallas, TX
Back to @property..could someone verify that my assumptions below are correct?

@property (assign) is the same as:
@property (retain) is the same as:
And lastly, @property (copy) is the same as:

http://developer.apple.com/document....html#//apple_ref/doc/uid/TP30001163-CH17-SW2

"assign
Specifies that the setter uses simple assignment. This is the default.

If your application uses garbage collection, if you want to use assign for a property whose class adopts the NSCopying protocol you should specify the attribute explicitly rather than simply relying on the default—otherwise you will get a compiler warning. (This is to reassure the compiler that you really do want to assign the value, even though it’s copyable.)"

"copy
Specifies that a copy of the object should be used for assignment. (The default is assign.)

The copy is made by invoking the copy method. This attribute is valid only for object types, which must implement the NSCopying protocol. For further discussion, see “Copy.”"

"retain
Specifies that retain should be invoked on the object upon assignment. (The default is assign.)

This attribute is valid only for Objective-C object types. (You cannot specify retain for Core Foundation objects—see “Core Foundation.”)"

From the documentation it seems like your examples for assign and copy are correct, but I can't tell for retain if it indicates everything you put in your example.

-Lee
 

Catfish_Man

macrumors 68030
Sep 13, 2001
2,579
2
Portland, OR
Roger. Thanks Krevnik!

Back to @property..could someone verify that my assumptions below are correct?

@property (assign) is the same as:

Code:
- (int)whatever
{
  return classVar;
}

- (void)setWhatever:(int)x
{
  classVar = x;
}

@property (retain) is the same as:

Code:
- (void)setWhatever:(NSObject *)o
{
  [o retain];
  [classVar release];
  classVar = o;
}

- (NSObject *)whatever
{
  [classVar autorelease];
  return classVar;
}

And lastly, @property (copy) is the same as:

Code:
- (void)setWhatever:(NSObject *)o
{
  classVar = [o copy];
}

- (NSObject *)whatever
{
  return classVar;
}

Almost correct. Two things though:

1) The setter for copy needs to release the old value since -copy increments the retain count

2) All of these only look like that if you also specify nonatomic. Otherwise it'll do some voodoo with locks to make sure that it remains consistent when being used from multiple threads. I think nonatomic is generally what is wanted.
 

EliseVanLooij

macrumors newbie
Jul 28, 2008
4
0
If you're going to do Objective-C 2, do it well

Forget all that, you don't need all that setting, getting and releasing junk in Objective-C 2.0, which is what you're using judging from your property declarations. All you need is this in your header file, as you more or less had:
Code:
#import <Cocoa/Cocoa.h>

@interface myClass : NSObject {
    NSString *myString;
    NSNumber *myInteger;
    NSObject *myObject;
}

@property (readwrite, copy) NSString *myString; //if a class confirms to the NSCopying protocol, specify copy
@property (readwrite, copy) NSNumber *myInteger; //ditto
@property (assign) NSObject *myObject; //assign is the default

@end

But in your implementation file, you only need this:
Code:
#import "myClass.h"

@implementation myClass

@synthesize myString; //this automatically implements -(void) setMyString: (NSString *)aString and -(NSString) myString. 
                      //Really, it does.
@synthesize myInteger;  //Because we want integer values here, we'll have to implement our own setter.
@synthesize myObject; //use @dynamic for Core Data ManagedObjects

- (void) setMyInteger: (NSNumber *)aNumber
{
    myInteger = [NSNumber numberWithInteger: [aNumber integerValue]];
}
// no custom -(NSNumber) myInteger getter needed, the automatically generated getter will return an integer value anyway.

@end

Apple's own The Objective-C 2.0 Programming Language is a great source of information, and, as always, Scott Stevenson is a great help: Theocacao: A Quick Objective-C 2.0 Tutorial
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.