If I declare an instance variable
#implementation Person {
NSString *name; // would this be atomic, strong, readwrite?
}
Does it get the same default attributes as if I declared it a property (atomic, strong, readwrite)
#interface Person()
#property NSString *name; // would be atomic, strong, readwrite by default
#end
ivars and local variables are strong by default (under ARC). Variables are read-write unless the appropriate use of const is applied. And variable access is non-atomic unless specific steps are taken to make the access atomic.
So essentially, ivars and local variables behave as strong, non-atomic, read-write.
Nope. Instance variables don't get attributes like atomic, strong, etc., at all -- those are only attributes that apply to properties. (If you're using ARC, they'll be treated as a strong variable, though.)
Related
I found the following code in my project (using ARC). It looks like there is no property adDisplay declared. Only a synthesized statement and the compiler doesn't complain about it.
#interface MyClass() <MyProtocol> {
AdDisplay * _adDisplay;
}
#end
#implementation
#synthesize adDisplay = _adDisplay;
...
#end
Do I need to add
#property (nonatomic, strong) AdDisplay * adDisplay;
if I want to make sure adDisplay is strongly retained?
thanks
Update: it is declared in the protocol indeed. Does that count as instance variable?
A property in Objective-C is a name for a pair of methods: a setter and a getter. Declaring a property means saying that these two methods exist (for readwrite properties).
There does not have to be any real storage or memory management. Historically, under manual memory management, assign, retain, or copy would affect how the methods are synthesized.
However, under ARC, this is no longer needed. When you declare a property as strong or weak, it does not affect the body of the method, but only the type of the ivar.
Since you have an ivar declared manually
AdDisplay * _adDisplay;
(as strong)
then strong or weak inside the #property declaration won't have any real effect, only as a documentation for the API consumers.
The following would also work:
#interface MyClass() <MyProtocol>
#end
#implementation
#synthesize adDisplay;
#end
Also note this used to be a common memory leak problem when migrating projects from MRC to ARC. A property declared as weak, with an ivar declared as 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.
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).
I'm looking for the syntax of the getter/setter. Which is the setter and which is the getter??
Is the readwrite attribute the getter?
Is the assign the setter?
#interface SomeClass : NSObject
{
NSString *str;
NSDate *date;
}
#property (readwrite, assign) NSString *str;
#property (readwrite, assign) NSDate *date;
Neither is the getter or the setter. readwrite controls whether a set method is generated or just a getter, and assign specifies the memory management scheme (in this case, the variables are not retained, which is probably a mistake).
For the full property declaration syntax, you can take a look at the relevant docs.
You should check out this page, it will explain things.
readwrite = the property can be read and written
assign = this is a property that doesn't need to be ref counted. (the alternative is 'retain,' which means that values of this property are retained when set and released when overwritten.
Neither. The code you posted is an interface declaration; getters and setters go in an #implementation context, and are usually created using the #synthesize directive, as in
#synthesize str;
#synthesize date;
There are a number of attributes that can go after a property declaration. In this case, the readwrite specifies that the value of the property can be set (using the someObject.str = #"foo" syntax); the opposite is readonly, which means that the value of the property cannot be set. assign—as opposed to copy or retain—means that the property's value gets set directly, whereas the latter two create a copy of the value and retain the value, respectively.
The getter and setter are two methods that are automatically created when you use #property. By default, the getter will have the same name as the property, the the setter will have the name prefixed with set and suffixed with :; for instance, for the property str, you would be able to call [someobj str] to get the str property, and [someobj setStr: somestr].
The readwrite and assign attributes provide some information about how this getter and setter should be defined, if you use #synthesize to create the definitions for you. readwrite simply says that you are allowed to set the property, and assign says how the property will be set. See the documentation for more info.
I have this structure:
#interface MyList : NSObject {
NSString* operation;
NSString* link;
}
#property (readwrite) NSString* operation;
#property (readwrite, assign) NSString* link;
#end
#implementation MyList
#synthesize operation,link;
#end
I know that if I had retain instead of readwrite I should release the operation and link properties.
BUT should I release the operation and link with the code above?
No. You did not New, Alloc, Retain, or Copy the values in there, so you do not (Auto)release them.
The default values are readwrite, assign, and atomic. So by not specifying assign, retain, or copy in your first example you are essentially using assign by default. This is why you wouldn't subsequently use a release. Assign does not increase the retain count of an object. Note that for objects such as your string you almost would never want to use assign because you don't own the object and it could get released on you. So for objects you want to use either retain or copy. You would only use assign on scalar types like floats, NSIntegers, BOOLs etc. Note also that if you are not using garbage collection you get a compiler warning if you don't specify assign, retain, or copy.