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.
Related
Coming from Java et al, I'm not clear on the difference between these two declarations:
#property (nonatomic, readwrite) NSInteger score;
#property (nonatomic, strong) NSMutableArray *cards;
Why is the pointer, *, not a requirement on both property declarations?
I've seen this a lot in local variables too:
- (void)viewDidLoad
{
[super viewDidLoad];
int foo = 1;
NSString *bar = #"foo";
}
What's the difference between static allocation of primitive type int and NS types?
Objective-C objects are always allocated on the heap, so you always access them through pointers. Variables of primitive (or struct) types can be, and typically are, allocated on the stack and accessed without pointers.
If you're familiar with Java, it's basically the same semantics. Primitive types are accessed and passed around by value, objects by reference. The difference is that ObjC has (by virtue of its C lineage) syntax explicitly marking that difference.
Type names that start with an uppercase prefix in Apple frameworks aren't all ObjC classes. NSInteger is a primitive type just like int, so you can and usually do use it without pointers.
pointer is always used for referring to something at the heap but not when you referring to something on the stack.But
for some primitive types and simple structure which are accessed via the stack so you don't need to use pointer..
NSInteger is a primitive type, that means it will be stored locally on the stack. there is no need to use a pointer to access it, but if you want to use pointer then you can.
You can have a pointer to an NSInteger if you really want to with following way:
NSInteger *pointerToProcessID = &yourNsintegervar;
If you look at the definition of NSInteger you'll see that it is a typedef for a simple integer. Basically, all the non-object types are stored as simple values, while the types that are complex objects are typically pointer properties. There are a couple reasons why these more complex objects are stored as pointers:
Using the value, itself, instead of the pointer would require copying (that is, if you use a pointer, you can put the object somewhere else and you only need to copy the much shorter address rather than all of the content that happens to be in that object, and hence it is more efficient that way).
When using a non-pointer type, it is necessary to know the required storage space, which works if you know the exact type of the object, but fails in the case of inheritance (e.g. an NSMutableArray may add additional fields to NSArray, for example. If you were to use NSArray instead of NSArray*, then assigning from an NSMutableArray would be broken, because the system would only have set aside enough space for the fields in the base class and not for the derived class. When using a pointer, however, since the pointer size is the same for both the base and derived types, one can assign the pointer for a derived type to a pointer to the base type, and still have things work correctly).
Note that it is possible and safe to use a pointer type with these primitive types, as well; however, this is not done for efficiency reasons (it would create additional allocation and dereferencing where not necessary).
first post. Sorry if I screwed up the code rules. I'm trying to learn Objective C from the Big Nerd Ranch Guide. I'll post the example dealing with strong references.
#import <Foundation/Foundation.h>
#interface Asset : NSObject
{
NSSTRING *label;
unsigned int resaleValue;
}
#property (strong) NSString *label;
#property unsigned int resaleValue;
#end
So basically the NSString needs a strong reference whereas the int does not. I'm aware that NSString is an object, and I've read that if nothing is specified a variable is given the property of assign.
So if assign is good enough to keep something like an int from being freed until the object owning it is freed, how come it's not good enough to keep the NSString object within the Asset object from being freed? Ultimately I guess I'm still confused about what assign does in terms of reference counting vs. what strong does (or perhaps I should say retain since that is what strong replaced in ARC).
strong == to std::shared_ptr if you come from C++
strong states that the object must be retained and released respectively during assignment.
-(void)assign:(id) b to:(id) a {
if( b ){
[b retain];
}
if ( a ){
[a release];
}
a = b;
}
To answer your second question, the size of an objective-C object is not defined like a structure. Thus obj-C classes can not be held by value.
Thus all data inside of an obj-c class compiled as obj-c will always have plain old data types stored within it since their size can be determined as fixed.
Consider a buffer of 8 bytes;
The first 4 bytes are for your int the second 4 bytes are your pointer, since having a variable length string would change the size of the object at run time you see how this wouldn't work, a string is allocated on the heap and assigned to your pointer.
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.
Using Xcode 4.2 and ARC, I notice that the auto-generated code for an NSManagedObject still reads like this for properties:
#property (nonatomic, retain) NSString * someString;
1) Shouldn't retain now be replace with strong or weak?
2) Why does the auto-generated code still use retain
3) What is the correct replacement for retain in this property statement?
I'm currently debugging a problem using NSFetchRequest, and I thought this might be the source of the problem. Thoughts?
1) Shouldn't retain now be replace with strong or weak?
No. You cannot replace retain with weak; they are different. And strong is a 100% synonym for retain; they are identical. You can use either, so there is no "should" here. You can replace retain with strong if you like, but you don't have to.
2) Why does the auto-generated code still use retain
Why not? See (1). retain is correct so there is no problem.
3) What is the correct replacement for retain in this property statement?
There is no need to replace retain.
I'm currently debugging a problem using NSFetchRequest, and I thought this might be the source of the problem. Thoughts?
It isn't.
To answer all three questions in one: retain and strong are synonymous with each other, so both are correct. The documentation states
retain implies __strong ownership
strong implies __strong ownership
Before ARC, you have to 'release' an object which is retained. That mean retain has counter part. After ARC you don't need to release. So use strong. Its a visual clue that you don't need to call release.
"retain" is equals to "strong".
"strong" is used for example:
#property (nonatomic, strong) NSString * someString;
And "__strong" is used for example:
-(void) someMethod
{
__strong NSString* vStr = [[NSString alloc] initWithString:#"some string"];
}
On Apple Docs. says:
Property Attributes
The keywords weak and strong are introduced as new declared property attributes, as shown in the following examples.
// The following declaration is a synonym for: #property(retain) MyClass *myObject;
property(strong) MyClass *myObject;
Apple doc. http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
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!