Pointers, primitives, and properties in Objective-C classes - objective-c

I really need some clarification — I have a few questions and I'm all mixed up right now.
Here is a simple class interface:
#import <UIKit/UIKit.h>
#interface Car : NSObject{
NSInteger carID;
NSString *carName;
}
#property (nonatomic, assign) NSInteger carID;
#property (nonatomic, copy) NSString * carName;
#end
Why is carID not declared as a pointer?
Why does it use "assign" for carID instead of "copy"?
Why even declare class members as pointers in the first place? (In my main program, my Car object will be used as a pointer.)

NSInteger is simply a typedef for a primitive type (int on 32-bit, long on 64-bit) — it is not an object, and can as such not be retained or copied.
Class members are always pointers; you never pass the "real" objects around; as that would be, at best, unmanageable.
Edit: To expand on the last paragraph: Objective-C class instances always exist on the heap, never on the stack; this is to facilitate things like reference counting and self-managed object life cycle.
This also means that it's very hard to accidentally copy an object; but on the flip side it can be somewhat easier to accidentally dispose of an object you still need. Still, the latter is more readily debugged (as it causes a nice, big crash (at best, anyway)) than the last (which at worst causes a slow leak).

The property for carID is not really correct. For types that are not pointers, the correct definition looks like:
#property (nonatomic) NSInteger carID;
It's always going to be copying a value anyway, but "copy" has a very different meaning in properties - for objects it's going to call [object copy] when that property is used to set a new value.
Or you could drop off the nonatomic, but then the property is more expensive to call (by some small amount). Just leave in the nonatomic unless you have a good reason not to.

Thanks guys!
So in Objective-C , you have int and Pointer Int.
How do you declare these in objective C
-int being a regular int.
-Pointer Int being an object representation of an integer. Since it is an object, it can also point to pointers*. Right?
And Pointer Int pointers can point to pointers of any type If I wanted to. Right?
It will cause a crash if it doesn't point to a Pointer int. But it will compile successfully, Right?
But in what scenarios would I prefer using a regular int to a Pointer Int?

I would like to add some clarification why you would want to use:
#property (nonatomic, copy) NSString * carName;
instead of
#property (nonatomic, retain) NSString * carName;
The copy keyword implies language semantics that you want to have a COPY of the NSString passed into your current object reference. So the pointer does not change (that is why you don't have to release the object ref).
The retain keyword makes it so that you get the pointer which will be retained because the pointer reference changes for this data member (and the current one will be released). Copying a NSString might not be a considerably heavy operation, so copying NSString is used often. You have to be careful what type of property you declare as copy. There might be a considerable amount of effort to produce a copy of types like Dictionaries etc (see shallow, deep copy etc).
Hope that helps!

Related

What kind of variables does ARC manage?

Could someone please clarify exactly what ARC manages? Ive heard it does not manage c-structs, but i still see people using them. Please tell me which of the varialbes below will be managed by ARC and why.
static CGPoint _var1;
int _var2;
#interface class1:NSObject
CGPoint _var3;
CGPoint _var4;
NSString *_var5;
NSString *_var6;
}
#property (assign) CGPoint var3;
#property (strong) NSString *var5;
#end
#implentation class1
#synthesize var3 = _var3;
#synthesise var5 = _var5;
#end
ARC manages Objective-C objects automatically. All other types are managed just as they always have been in C.
Note that in your example, there is no allocation associated with the CGPoint instance variables; there memory is effectively allocated inline with the object.
Compared to MRC (as opposed to GC - which is now deprecated) ARC manages Objective-C objects - no retain, release or autorelease.
In general it does not manage core foundation objects - for those CFRetain and CFRelease are still required.
ARC does not manage C objects allocated with malloc and friends, for those manual memory management is required.
C structures are not dynamically allocated, they are value types just like integers and characters. If you declare pointers to C structures and dynamically allocate them using malloc and friends then you manage those manually as with any other dynamically allocated C object.
What you have have heard about in relation to ARC and C structures is a change to what field types are allowed. Under MRC the declaration:
typedef struct
{
int count;
NSString *name;
} Item;
is valid and name is managed manually using the usual retain etc. However with ARC it is disallowed, no object reference managed by ARC may be used as a field type in a structure.
The recommended alternative for the above structure is to use an Obj-C object instead. However if you really need value semantics the field can be marked with the __unsafe_unretained attribute:
typedef struct
{
int count;
__unsafe_unretained NSString *name;
} Item;
This attribute instructs ARC to ignore any reference stored into the name field for the purposes of determining whether an object should be retained or released. ARC may at any time release an object referenced by name, hence unsafe & unretained. To use such a structure safely you must ensure that the object referenced is kept around by others means, e.g. by having a strong reference to it that ARC is managing.

copy property and Block_copy(myBlock) / [myBlock copy]

Consider:
typedef void (^select_block_t)(UIView *) ;
(1) #property (copy, nonatomic) select_block_t myBlockProperty ;
(2) #property (strong, nonatomic) select_block_t myBlockProperty ;
(3) #property (assign, nonatomic) select_block_t myBlockProperty ;
and:
(A) self.myBlockProperty = ^(UIView *) {NSLog(#"Hi");} ;
(B) self.myBlockProperty = [^(UIView *) {NSLog(#"Hi");} copy] ;
I am trying to understand what is the correct way to map which property declaration with which block copy semantics
I have seen examples here on S.O. that would favor[1:B]
But then I get confused by how redundant the 'copy' operation is.
My limited understanding is that [1:A] should be correct, because I want
the block to be copied once when I assign the property, not once at block creation and then once again at property assignment time.
[3:B] would also make sense according to my rationale. So, what am I misunderstanding?
[1:A] is correct, yes. [3:B] is incorrect because:
it's not clear that the class owns the property, so should release it in dealloc (but it should)
the setter (B) looks like a leak, and the static analyser might flag it as such, because the block is copied, handed to a property, then leaves the scope with retain count +1.
using (3) means that it only works if you set a heap-block (a copied block) with a retain count of one. This leaves plenty of margin for error when using the property. (1) works with both stack-blocks and heap-blocks, and will also correctly retain auto-released blocks.
EDIT: I see you're using ARC. In that case, it's not possible to use [3:B] at all. The compiler will release an object (even when copyed) once it's out of scope, and this property setter won't have retained it. Therefore the property will contain a bad pointer, it's an EXC_BAD_ACCESS waiting to happen.

Are Mutable classes "heavier?"

On some intuitive (perhaps wrong) idea of performance, I always get a copy of a mutable instance before I store it. So if a property expects an NSArray I take the mutable array I'm working with and store it as self.array = mutableArray.copy (though the property is specified as strong or retain).
This seems silly to me, suddenly, but is it? Do mutable instances -- doing the exact same task -- perform the same?
Note: The mutable instance falls out of scope and (thanks to ARC) gets released right after this, so there's no worry that it'll be mutated once it's assigned to the property.
NSArray and NSMutableArray are both (as far as I'm aware) implemented on top of CFArray, which simply has a flag specifying whether it's mutable. CFArray functions which require a mutable array have an assertion right at the beginning, checking that flag:
void CFArraySetValueAtIndex(CFMutableArrayRef array, CFIndex idx, const void *value) {
// snip...
CFAssert1(__CFArrayGetType(array) != __kCFArrayImmutable, __kCFLogAssertion, "%s(): array is immutable", __PRETTY_FUNCTION__);
Mutable and immutable CFArrays are identical other than passing or failing this assertion, and so should NSArrays and NSMutableArrays be, performance- or other-wise.
Partly answered here: NSArray size and mutability
NSMutableArray is not noticeably slower or larger (memory-wise) than an NSArray. It's basically just an NSArray that reallocates itself when it gets full as as bigger array, and keeps doing that as you add items to it.
The reason for copying mutable arrays as immutable ones when assigning them to values in your class is so you can guarantee that their values don't change. If you store a mutable array in your class, other code can change its values outside of your class without calling any of your methods. That leaves you vulnerable to crashes due to internal inconstancy errors within your classes.
For example, supposing that when the array was set, you cached the length of the array as an int property in your class. That would be fine if the array was immutable, but if it was mutable, someone else could change the array, and your cached value would now be wrong, but you have no way of knowing that.
However, it's not necessary to do the copying manually. If you declare your array properties as:
#property (nonatomic, copy) NSArray *foo;
Then whenever you assign an array to object.foo, it will automatically be copied. You don't need to copy it again yourself. It's best practice to use a property type of copy instead of strong/retain for any type that has a mutable variant, like so:
#property (nonatomic, copy) NSArray *foo;
#property (nonatomic, copy) NSString *foo;
#property (nonatomic, copy) NSDictionary *foo;
#property (nonatomic, copy) NSData *foo;
etc...
However be careful not to use it for mutable properties, or it will make an immutable copy stored in a property that thinks it's mutable and cause a crash if you try to mutate it. The synthesised copy property isn't smart enough to use mutableCopy automatically.
#property (nonatomic, copy) NSMutableArray *foo; //don't do this
For clarity you're asking if, given an NSArray and an NSMutableArray both subjected to a battery of non-mutating test methods, does the NSArray perform noticeably faster? I specify non-mutataing, because it looks like you're copying a mutable array to an immutable array with the belief that the immutable array will perform its non-mutating methods faster than the mutable array. Anyways, the answer is no. (But don't take my word for it; profile).
Even if NSMutableArray overrode some non-mutating methods (which we can't know about, one way or another), you wouldn't need to worry about it. Adding a couple CPU cycles is trivial compared to the overall computational complexity of the operation. As long as NSMutableArray doesn't manage to turn a O(n) lookup-operation into a O(n2) operation, you'll be fine 99% of the time. (Those complexities are just fictitious examples).
While there are perfectly valid reasons why you might want to copy a mutable array into an immutable array (as pointed out by #NickLockwood), performance shouldn't be one of them. Premature optimization is very bad, after all.

Property - Implementation of variables in Objective-C

Well ! I got confused about the way of declaring variables & implementing its properties.
The .h File contents
#interface XYZAppDelegate : NSObject <UIApplicationDelegate> {
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet XYZViewController *viewController;
#end
The .m File Contents
#import "XYZAppDelegate.h"
#import "XYZViewController.h"
#implementation XYZAppDelegate
#synthesize window=_window;
#synthesize viewController=_viewController;
My questions/Queries are as follows.
Don't we require to declare variables if we put property ? ( Using property, we can indirectly declare variable - is it like that ? )
What are the additional features other than this ? ( In coding specific )
Why does everybody insist to use _ before each property accessor ? ( Other than security threats ? Has it become coding standard ? Whats the reason behind it? )
You do not have to declare the
variable. It is done automatically,
I believe by #synthesize. One
advantage to declaring it is that the
debugger will automatically list it.
Weigh this against the ugliness of
redundant definition.
Other features: read only properties,
assigned (unretained) values.
The underscore is a convention for
naming member variables that are
differently named than properties and
method variables. Apple's samples
sometimes use this convention and
sometimes do not. I view it as
usually unnecessarily verbose as a
programmer can easily tell the
difference between myVariable and
self.myVariable.
1) Don't we require to declare variables if we put property ? ( Using property, we can indirectly declare variable - is it like that ? )
No. You aren't required to declare variables for the corresponding properties. You are required to use the #synthesize propertyName command which tells the compiler to create those variables for you.
2) Why does everybody insist to use _ before each property accessor ? ( Other than security threats ? Has it become coding standard ? Whats the reason behind it? )
Most people (all?) have been stung by memory management nightmares. Some of these are caused by sloppy/lazy/zero-sleep coding. Using #synthesize propertyName = _propertyName allows the programmer to immediately know that the underscored variable is private to the class, and is unretained. It prevents issues where you specifically allocate or copy an object to store in the property, or accidentally assign an autoreleased object to the ivar.
Consider:
1) An autoreleased object being assigned to an unretained ivar.
#synthesize propertyName;
propertyName = [NSString stringWithFormat:#"I've just made %#", "a boo-boo."];
"propertyName" now references an object that will soon not exist, which will create EXEC_BAD_ACCESS errors down the road (as soon as it's referenced again).
2) A retained object being set to the retained property.
#synthesize propertyName;
self.propertyName = [[NSString alloc] initWithFormat:#"I just created %#", #"a leak"]
Now we've created an NSString object, and set it to the propertyName property, which itself is retaining the variable. Now the object is double retained and won't be properly released.
Both of these issues are easy to combat (even when tired, albeit less so) when you properly name your ivars with an underscore. It's not a fool-proof method, but it makes it considerably easier to manage the retain counts of objects in your head.
(1) No, not with the new 64-bit only features. The variables are declared for you, automatically.
(2) I don't know what you're asking here.
(3) It's just a convention, so that the variable name is different from the accessor name. Makes it clearer which you're dealing with.

c-style member vars in obj-c

I've noticed that I cannot use the #property / #synthesize for member vars that are arrays in obj-c. For instance the member var int mVar[5] cannot use the #property/#synthesize.
However, I've noticed that I can set these vars simply by not using self.mVar[n] but instead using mVar[n].
Can someone explain why this works, if this is good or terrible practice, and what alternative I should use if it is not good practice?
Properties are syntactic sugar for set/get-style methods. Passing arrays in as parameters and out as return values via these methods is fraught with semantic and performance problems, so they probably just put them in the too-hard basket and deliberately excluded them.
As regular data members, arrays don't exhibit these difficulties because you are accessing them directly rather than copying them in and out via methods.
If you want to make the contents of an array accessible as a property (which you should only need to do if you want to make the contents public), you can expose them as:
#property (readonly) int *vars;
#property (readonly) int numVars;
Or you could do the Objective-C thing:
#property (nonatomic, retain) NSArray *vars;
But then you would have to create lots of NSNumber objects (ick).