In case of #property without ivar what's difference between strong, weak and assign? - objective-c

I want to declare #property without ivar. Is there any difference if I declare #property with strong, weak or assign ?

The #property declaration defines a contract with the user's of the property. If it is declared as weak, for example, then the user of the property knows that the passed object won't be retained.
This contract should be true whether the property is backed by an ivar or not.
In your case, the property should be strong, weak, or assign depending on your implementation of your property and the contract you wish to provide for the property.

It depends of what type the property is. For example for primitive types like NSInteger you can't declare property with strong or weak attributes. Xcode will show you an error.
So these declarations are invalid:
#property (nonatomic, strong) NSInteger max;
#property (nonatomic, weak) NSInteger max;
#property (nonatomic, copy) NSInteger max;
because strong, weak and copy are attributes of object types and NSInteger isn't object type. It's primitive type. Thus, following declaration is valid:
#property (nonatomic, assign) NSInteger max;
Attributes assign, weak, strong, copy and unsafe_unretained specify memory management rules for ivar that is backed by property. So if you are not going to create ivar for property (suppose you want to provide your own getter/setter and property will not store any value) it doesn't matter what attribute you'll specify. But as I mentioned above you couldn't specify attributes of object types for primitive types.

Related

Why does ARC conversion add "weak" decorator to "readonly" properties?

I'm just updating a really old project to ARC (2017 – I know).
I've noticed that for readonly property declarations, it's adding a weak decorator. Eg:
// Before conversion to ARC:
#property (nonatomic, readonly) NSString *defaultName;
// After conversion to ARC:
#property (weak, nonatomic, readonly) NSString *defaultName;
Could someone explain why it's doing this?
There are a few SO questions and answers about the meaning of weak, strong and copy when applied to a readonly property. An example is this which seems to be directly contradicted by this – I don't really see how it makes sense as they only seem to apply on setting a property and a readonly has an explicit getter method.
Before the introduction of ARC, the default memory attribute was assign, therefore
#property (nonatomic, readonly) NSString *defaultName;
was the same as
#property (nonatomic, assign, readonly) NSString *defaultName;
That should explain you why ARC migration uses weak.
This changed when ARC was introduced - for object types strong/retain became the default.
This attribute affects only the setters anyway, therefore for readonly properties the attribute can have any value.

What's the difference the member variable between in a interface and #property (nonatomic, strong)?

#interface ChargeView (){
NSString* billid;
int clickRow;
NSMutableArray *arr1;
}
#property (nonatomic, strong) NSMutableArray *arr2;
What's the difference between arr1 and arr2? Which is better or write it anywhere if I like?
The property also generates the accessors -(NSMutableArray *)arr2 (getter) and -(void)setArr2:(NSMutableArray *)arr2 (setter). It further generates a corresponding instance variable _arr2 (the underscore is convention for ivars). The attributes of the property determine the behavior of the accessors. For instance, if the property is marked atomic, the accessors will synchronize access to the ivar.
On the other hand, arr1 is just an ivar and you have to write accessors (if you need any) yourself.

iOS readonly and retain are mutually exclusive

I want to have a strong readonly property. When I use this code:
#property (strong, nonatomic, readonly) NSString *test;
I get a warning: "Property attributes 'readonly' and 'retain' are mutually exclusive". How can I solve this warning?
Create a property in your continuation category which redefines the variable as readwrite:
#property (strong, nonatomic, readwrite) NSString *test;
Now, publicly the property is read only, but privately you can write it. The compiler will generate the methods you need and allow you to call them.

property_getAttributes() does not make difference between retain, strong, weak and assign properties when set read-only

I'm trying to get the property attributes of an object with the property_getAttributes() runtime function. Some properties are set read-only. But the problem comes when I try to make the difference between retain/strong, weak and assign properties. e.g.:
Let's say we have:
#interface MyObject : NSObject
#property (assign, readonly) NSObject *prop1;
#property (strong, readonly) NSObject *prop2;
#property (weak, readonly) NSObject *prop3;
#end
We get the property list and print
int outCount;
objc_property_t *properties = class_copyPropertyList([MyObject class], &outCount);
for(i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
const char *c_attributes = property_getAttributes(property);
printf("%s", c_attributes);
}
free(properties);
The result is:
T#"NSObject",R,V_prop1
T#"NSObject",R,V_prop2
T#"NSObject",R,V_prop3
...so no specific code for weak, strong/retain, assign properties when they are read-only :(
The question is: is there any other way to know if the property is weak, strong/retain, assign?
I haven't tried your code, but according to
https://developer.apple.com/library/mac/documentation/cocoa/conceptual/objcruntimeguide/articles/ocrtpropertyintrospection.html
R The property is read-only (readonly)
C The property is a copy of the value last assigned (copy).
& The property is a reference to the value last assigned (retain).
N The property is non-atomic (nonatomic).
G The property defines a custom getter selector name. The name follows the G (for example, GcustomGetter,).
S The property defines a custom setter selector name. The name follows the S (for example, ScustomSetter:,).
D The property is dynamic (#dynamic).
W The property is a weak reference (__weak).
P The property is eligible for garbage collection.
t Specifies the type using old-style encoding.
To answer your question quickly, the answer is no.
The issue here is that memory management semantics for properties (those are assign, unsafe_unretained, strong, weak, copy in ARC and assign, retain, copy in MRC) only have any application in automatically generated setter code. Should you write your own setter for the property you are of course encouraged to implement the semantic yourself (but not required). The getter of these properties are not modified at all by these property attributes. Consider this code:
#interface FooBar ()
#property (nonatomic, strong, readonly) NSString* foobar;
#end
#implementation FooBar
- (NSString*) foobar {
return [NSString stringWithFormat:#"aString"];
}
In these situations the caller will make a either a strong or weak reference and the return value must live for at least as long as the calling code needs to complete the statement. In the case of a weak reference it will go to nil afterwards since a property with strong does not guarantee that the referenced object will be kept for you. Ultimately, memory management on readonly properties are nothing more than a placebo that end up there mostly by either habit or style #property (nonatomic, readonly) ... is perfectly legal, but confusing when we are used to encountering a memory attribute in the property declaration.
PS: There's another function in the runtime called property_copyAttributeList which I find much easier for parsing this information (it uses structs to break up the components for you).

Making the getter/setter of an int?

#property (retain) int myInteger;
That throws me an error because apparently int is not considered an object... but I want to get the advantage of creating a getter/setter method with the #synthetize thing, but with an int. How could I achieve so? Is there an equivalent?
#property (assign) int chunkID;
or
#property (readonly) int chunkID;
You cannot retain a primitive type like integers. Only objects can be retained...
Use this:
#property (nonatomic, assign) int chunkID;
assign is the default so you might want to leave it out.
You need to use the assign type of property because you are dealing with a primitive object type (i.e. int). This kind of type can't be retained.
Only subclasses of NSObject can be retained / released.