XCode 4 c array of objective-c objects - objective-c

With XCode 3 compiler, I could manage an array of objects like:
#interface myView:UIView
{
CALayer *layer[4];
}
#property (nonatomic,retain) CALayer **layer;
#end
#implementation myView
#dynamic layer;
- (CALayer **)layer { return layer; }
// I could then access elements like
- (void) example
{
self.layer[3] = NULL;
}
#end
With XCode 4 compiler the #property declaration generates an error "Property with retain must be an object type".
I guess best way to fix is to convert to NSArray, but I have 100's lines of code using the c-style array subscript (e.g., self.layer[i]). Is there some other way to fix?

Several problems with this code:
It should be MyView, not myView; classes start with capital letters.
CALayer ** is not an object type; it is a pointer to an object type, hence the compiler complaint. Simply making it assign will make it compile, but it'll still be wrong.
There is likely no reason to use a language array (MyClass foo[4]) to hold this data. Use an NSMutableArray (you can use [NSNull null] as a stand-in for "this slot is not populated".
If you really want to stick with the language array, drop the retain. Just remember that you have to explicitly manage the retain/releases of the objects within the array. The #property won't do that for you.
Also, while it may seem a pain to fix your code to be inline with typical standard patterns, it is only going to be more costly to do so as the code evolves and, someday, you'll likely be in a situation where you really need to do so....

Change it to an assign property so you don't try to retain a non-object?

You cannot use Objective-C memory management calls (i.e. retain) on a C array. You need to manage your array using standard C or C++ logic. You need to malloc and free memory on your own. If you do not need to retain the array then you can remove the retain property.

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.

Where are the synthesized ivars stored?

I've been reading up on the automatically synthesized ivars. My question is, "WHere are automatically they allocated?" I would have expected them to be part of self, so that I could see them in the debugger, but it seems that the only way I can see them is by invoking the accessor method (via the gdb 'po' command). Isn't there space in the class/object's struct (as there would be for an explicitly declared ivar)?
(Is there a description of the in-memory representation for a modern Objective-C object?)
Being a C guy, it makes me very uncomfortable to not to be able to see where everything is. :-P
Looks like this will tell you:
How do automatic #synthesized ivars affect the *real* sizeof(MyClass)?
I am a C guy at heart too. Why bother using these auto generated ones? I like looking at a class and seeing what it holds onto in terms of data.
Interesting: Neat how they took the 64 bit change to make things better.
http://www.sealiesoftware.com/blog/archive/2009/01/27/objc_explain_Non-fragile_ivars.html
They are added to the objective-c object (which is a C structure) no different to a regular ivar, so for example:
#interface TestObject : NSObject {
}
#property (nonatomic, assign) int theInt;
#end
#implementation QuartzTestView
#synthesize theInt;
#end
You can refer to theInt ivar directly (not through property accessors) either:
- (void)someMethod {
theInt = 5;
}
OR
- (void)someOtherMethod {
self->theInt = 10;
}
See http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html - using the modern runtime an instance variable "will be synthesized for you". It can be nice to add a variable yourself instead though (so that you can see it when debugging in self), however you have to be careful not to do direct assignments to the instance variable for retain or copy based properties.

Objective-C synthesize property name overriding

I am trying to understand the purpose of the synthesize directive with property name overriding. Say that I have an interface defined as follow:
#interface Dummy ... {
UILabel *_dummyLabel;
}
#property (retain, nonatomic) UILabel *dummyLabel;
And in the implementation file, I have:
#synthesize dummyLabel = _dummyLabel;
From what i understand, "dummyLabel" is just an alias of the instance variable "_dummyLabel". Is there any difference between self._dummyLabel and self.dummyLabel?
Yes. self._dummyLabel is undefined, however _dummyLabel is not.
Dot syntax expands out to simple method invocations, so it's not specific to properties. If you have a method called -(id)someObject, for example in the case of object.someObject, it will be as if you wrote [object someObject];.
self.dummyLabel //works
self._dummyLabel //does not work
dummyLabel //does not work
_dummyLabel //works
[self dummyLabel]; //works
[self _dummyLabel]; //does not work
Your understanding is incorrect. dummyLabel is the name of the property, and is not an alias for the instance variable - the instance variable is only called _dummyLabel. So the following holds for an instance of Dummy called myObject:
[myObject dummyLabel] works
myObject.dummyLabel works
[myObject _dummyLabel] fails
myObject._dummyLabel fails
myObject->dummyLabel fails
myObject->_dummyLabel depends on the visibility of the ivar (#public, #private, #protected)
[myObject valueForKey: #"dummyLabel"] works
[myObject valueForKey: #"_dummyLabel"] depends on the implementation of +accessInstanceVariablesDirectly (i.e. it will work in the default case where +accessInstanceVariablesDirectly returns YES).
The advantage of having another name
for the ivar than for the property is
that you can easily see in the code
when you are accessing one or the
other - Andre K
I'm not able to find a 'comment' button so I'm having to post as an 'answer'.
Just wanted to expand on Andre's comment - by knowing when you are using the synthesized properties vs the vanilla variable, you know (especially in case of setters) when a variable is being retained/copied/released automatically thanks to your nice setter, vs being manipulated by hand.
Of course if you are doing things right, you probably don't need the help of a setter to retain/release objects properly! But there can be other scenarios too where referring to your ivars as self.ivar instead of _ivar can be helpful, such as when you are using custom setters/getters instead of the default synthesized ones. Perhaps every time you modify a property, you also want to store it to NSUserDefaults. So you might have some code like this:
#interface SOUserSettings : NSObject {
BOOL _autoLoginOn;
}
#property (nonatomic, assign) BOOL autoLoginOn;
#end
#implementation SOUserSettings
#synthesize autoLoginOn = _autoLoginOn;
- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue {
_autoLoginOn = newAutoLoginOnValue;
[[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:#"UserPrefAutoLoginOn"];
}
#end
Note: This is just illustrative code, there could be a thousand things wrong with it!
So now, in your code, if you have a line that says _autoLoginOn = YES - you know it's not going to be saved to NSUserDefaults, whereas if you use self.autoLoginOn = YES you know exactly what's going to happen.
The difference between _autoLoginOn and self.autoLoginOn is more than just semantic.
I don't see any big advantage of
renaming _dummyLabel to dummyLabel
In some ObjC runtimes you have a hard time making instance variables invisible to users of the class. For them sticking some prefix (or suffix) on your instance variables can make it clear (or more clear) that you don't want anyone messing with your variables. However you don't want that gunk on your public functions. This lets you get it off.
It could also be useful if you need to maintain an old interface with one set of names at the same time as a new set of APIs with a new set of names (setLastname vs. setSurname).
Old post, but I think its important to mention, that it is recommended to access variables via getters and setters (so, with dot notation). Accessing a field directly (_ivar) is strongly recommended only when initializing it.
There is some good Apple's article:
https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
Last paragraph:
You should always access the instance variables directly from within
an initialization method because at the time a property is set, the
rest of the object may not yet be completely initialized. Even if you
don’t provide custom accessor methods or know of any side effects from
within your own class, a future subclass may very well override the
behavior.

Pointers, primitives, and properties in Objective-C classes

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!

Accessing a property from a C method in Cocoa

I'm trying to learn Objective C & Cocoa, but I just can't manage to access a property inside an Object. Specifically an object from a C method. I'm working with the chipmunk dynamics library.
Chipmunk has something similar to NSPoint called cpVect. Now I have no problem defining a cpVect inside my object, but when I try to make the accessors using #property & #synthesize I keep getting errors: so
#interface ControlsLayer : Layer {
Sprite * touchMarker, *dragMarker;
cpVect * forceVector;
}
works fine
but
#interface ControlsLayer : Layer {
Sprite * touchMarker, *dragMarker;
cpVect * forceVector;
}
#property (retain) cpVect forceVector;
#end
gives me the error "property 'forceVector' with 'retain' must be of object type"
so without 'retain' i get an different error
"type of property 'forceVector' does not match type of ivar 'forceVector'"
I'm going round in circles trying to figure this out, is there a particular type I can use, is it an incompatibility between chipmunk and cocoa, or... or.... I don't know. Chipmunk is very light on the documentation and all the examples I've found don't seem to use objects, all the examples just use one class to process everything.
Any help, greatly appreciated. This thing is driving me nuts.
The error your are getting is because the semantics of retain (ie. reference counted memory management, with the setter incrementing the ref count on the new value and decrementing the ref count of the old value) only make sense for Objective-C objects. The default semantics for properties are retain, but you can specify that the property be assign like so:
#property (assign) cpVect *forceVector;
where I assume that the property is actually a cpVect*, not a cpVect as you've written.
You've got a pointer to a cpVect in your instance Variable but not in your property.
Try this:
#property (assign) cpVect * forceVector;