Questions about @property

Discussion in 'Mac Programming' started by CaptSaltyJack, Jul 23, 2008.

  1. CaptSaltyJack macrumors 6502

    Joined:
    Jun 28, 2007
    #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.
     
  2. HiRez macrumors 603

    HiRez

    Joined:
    Jan 6, 2004
    Location:
    Western US
    #2
    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.
     
  3. CaptSaltyJack thread starter macrumors 6502

    Joined:
    Jun 28, 2007
    #3
    You would copy vars of type NSNumber, or NSNumber* ? (or both?)

    BTW:

    best sig ever :)
     
  4. Krevnik macrumors 68040

    Krevnik

    Joined:
    Sep 8, 2003
    #4
    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.
     
  5. CaptSaltyJack thread starter macrumors 6502

    Joined:
    Jun 28, 2007
    #5
    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?
     
  6. Krevnik macrumors 68040

    Krevnik

    Joined:
    Sep 8, 2003
    #6
    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.
     
  7. CaptSaltyJack thread starter macrumors 6502

    Joined:
    Jun 28, 2007
    #7
    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;
    }
    
     
  8. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #8
    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
     
  9. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #9
    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.
     
  10. EliseVanLooij macrumors newbie

    Joined:
    Jul 28, 2008
    #10
    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
     

Share This Page