Article source: www.cnblogs.com/andyque/arc…
At sign property and at sign synthesize in pairs, automatically generating access methods for a class member variable. In Xcode4.5 and later, the @synthesize can be omitted. \
Before, many netizens were confused about the use of Property in the tutorial I translated. They didn’t know when to release and when to self. XXX = nil. It is also unclear about objective-C memory management and cocos2D memory management rules. This article mainly explain objc @ property inside, what is it, what’s the use of it, atomic, nonatomic, readonly, readwrite, assign, retain, copy, getter, what’s the use of these keywords setter, when to use them. As for Objc’s memory management and Cocos2D’s memory management, I will translate Ray’s three tutorials and discuss them in detail. Our main task today is to get @property right.
Struct /class access qualifiers (public,protected,private) can be used to define struct/class access. Number to access its internal data members. Such as
//in Test.h
Copy the code
class Test
{
public:
int i;
float f;
};
Copy the code
I can use this class in main as follows :(note that if I use this class in main, besides including the header file, it is important to change main.m to main.mm, otherwise I will get some strange errors. So, whenever we use c++ and get a weird error, remind yourself to change the corresponding source file to the.mm suffix. Other files that reference this class are sometimes changed to.mm files.)
//in main.mmCopy the code
Test test; test.i =1; Test. F = 2.4 f; NSLog(@"Test.i = %d, Test.f = %f",test.i, test.f);Copy the code
But can we do that in OBJC? Look at the following code :(create an objc class called BaseClass)
//in BaseClass.h
Copy the code
@interface BaseClass : NSObject{
@public
NSString *_name;
}
Copy the code
Next, inside main.mm:
BaseClass *base= [[BaseClass alloc] init];
base.name =@"set base name";
NSLog(@"base class's name = %@", base.name);
Copy the code
Xcode4 displays an error without waiting for you to compile.
Property ‘nam’ not found on object of type BaseClass*” BaseClass does not have a Property named name. Even if we declare @public in our header file, we still can’t use it when we’re using BaseClass. Number to directly access its data members. @public,@protected, and @private only affect the access rights of the classes that inherit them. If you declare a data member using @private, then you cannot directly use the private member of the parent class in a subclass, just like in c++ or Java.
The compiler says there is no @property, so let’s define the property.
//in BaseClass.h
@interface BaseClass : NSObject{
@public
NSString *_name;
}
@property(nonatomic,copy) NSString *name;
//in BaseClass.m
@synthesize name = _name;
Copy the code
Now compile and run, ok, good. So you might be asking if @prperty just made the “.” legal? You can use it as long as you define @property. To access the data members of the class? Let’s take a look at the following example:
@interface BaseClass : NSObject{
@public
NSString *_name;
}
//@property(nonatomic,copy) NSString *name;
-(NSString*) name;
-(void) setName:(NSString*)newName;
Copy the code
I commented out the @property definition, and defined two other functions, name and setName. See the implementation file below:
//@synthesize name = _name;
-(NSString*) name{
return _name;
}
-(void) setName:(NSString *)name{
if (_name != name) {
[_name release];
_name = [name copy];
}
}
Copy the code
Now, you compile and run, and it works just as well. According to? Because WHAT I just did is exactly what I declared @property did earlier. @prperty is just an instruction for the compiler to compile and generate getter and setter methods for you. Also, notice the copy argument inside the parentheses of the plane property(nonatomic,copy)? All it does is
_name = [name copy];
Copy the code
If you specify retain or assign, the corresponding code is:
//property(retain)NSString* name;
_name = [name retain];
//property(assign)NSString* name;
_name = name;
Copy the code
And the other thing you can see from this point of view is that @property doesn’t just generate getters and setters, it also does memory management. But I’m not going to talk about that. Now, @property has probably done something that you already know. However, we programmers have a problem, that is, we do not fully understand the things, the heart is not practical to use, especially myself. So, next, let’s dig into every detail of @property.
First, let’s look at the difference between atomic and nonatomic. First, let’s look at the following code:
@property(nonatomic, retain) UITextField *userName; //1 @property(nonatomic, retain,readwrite) UITextField *userName; //2 @property(atomic, retain) UITextField *userName; //3 @property(retain) UITextField *userName; //4 @property(atomic,assign) int i; // 5 @property(atomic) int i; / / 6Copy the code
@property int i; / / 7Copy the code
Ask the reader to stop and think, what’s the difference?
The above codes 1 and 2 are equivalent, 3 and 4 are equivalent, 5,6,7 are equivalent. That is, atomic is the default, assign is the default, and readwrite is the default. But if you say @property(nontomic)NSString *name; A warning will be issued, as shown below:
Because non-GC objects are garbage collection objects, the default assign modifier does not work. So when do you use assign, and when do you use retain and copy? The recommended practices are to use copy for NSStrings,delegate for NSStrings, and delegate for NSStrings (and always use assign, don’t ask why, just use it, you’ll see later), and assign for non-objC data types, such as ints, floats, and other basic data types. While other objC types, such as NSArray, NSDate use retain.
Deep copy copy:NSString // similar to C++ string class, requires deep copy
Shallow copy retain: NSArray, NSDate
By default the assign: delegate, int, float, double, NSInteger, id
Before we continue, I just want to add a few questions, is it ok if we define setter methods for some variables, but we want the compiler to generate getters for us? The answer is absolutely yes. If you implement setter/getter methods yourself in a.m file, the translator will not regenerate the getter/setter for you. Take a look at the following code:
@interface BaseClass: NSObject{@public NSString *_name; } @property(nonatomic,copy,readonly) NSString *name; -(void) setName:(NSString*)newName; @interface BaseClass: NSObject{@public NSString *_name; } @property(nonatomic,copy,readonly) NSString *name; Readonly is declared, but no getter is generated, because you define your own getter below. -(NSString*) name; // Is the getter only name? Not necessarily. If you open up foundation.framework, go to uiview.h, and look at the property inside) -(void) setName:(NSString*)newName; @interface BaseClass: NSObject{@public NSString *_name; } @property(nonatomic,copy,readwrite) NSString *name; @interface BaseClass: NSObject{@public NSString *_name; } @property(nonatomic,copy) NSString *name; // Since readwrite is the default behavior, it is the same as code 3Copy the code
The above four pieces of code are equivalent. Next, look at the following four pieces of code:
// synthesize name = _name; // The compiler sees that you haven't defined any getter and setter, so it generates both getter and setter at the same time. // Because you define name, the getter method, the compiler will only generate the setter method, the setName method. -(NSString*) name{ NSLog(@"name"); return _name; } // synthesize name = _name; -(void) setName:(NSString *)name{NSLog(@"setName"); if (_name ! = name) { [_name release]; _name = [name copy]; } // synthesize name = _name; // Here you define your own getter and setter, this sentence is useless, you can comment out. -(NSString*) name{ NSLog(@"name"); return _name; } -(void) setName:(NSString *)name{ NSLog(@"setName"); if (_name ! = name) { [_name release]; _name = [name copy]; }}Copy the code
These four pieces of code are also equivalent. See here, you will have a further understanding of the function of Property. But, you have to be careful, if you’re using Property, and you’re overwriting the setter/getter yourself, you need to know exactly what you’re doing. Don’t write the following code, which is legal but misleading:
//BaseClass.h @interface BaseClass : NSObject{ @public NSArray *_names; } @property(nonatomic,assgin,readonly) NSArray *names; Assign -(void) setNames:(NSArray*)names; //BaseClass.m @implementation BaseClass @synthesize names = _names; -(NSArray*) names{ NSLog(@"names"); return _names; } -(void) setNames:(NSArray*)names{ NSLog(@"setNames"); if (_name ! = name) { [_name release]; _name = [name retain]; // You retain, but you don't override this method. The compiler generates setNames, which must be assigned}}.Copy the code
Copy the code
This becomes a problem when someone else uses @Property for memory management. To summarize, if you implement the getter and setter, atomic/nonatomic/retain/assign/copy these just advice to compile, compilation will be the first to your code to look for, if you define the corresponding getter and setter, so good, With you. If not, the compiler will according to atomic/nonatomic/retain/assign/copy which you specify certain rules to generate the corresponding getter and setter.
\
Well, with that said, let’s get back to business. The difference between atomic and nonatomic:
If you use the @synthesize to make the compiler generate code, the code generated by atomic and nonatomic is different. If you use atomic, as the name implies, it guarantees that every getter and setter operation will complete correctly without worrying about other threads setting when you get, thus ensuring a certain level of thread-safety. However, I did some research online, and it’s naive to rely solely on atomic thread safety. To write thread-safe code, you also need synchronization and mutexes.
Nonatomic, on the other hand, does not have the same “thread-safety” guarantee (which I use quotes to mean some degree of thread-safety). Therefore, nonatomic is obviously faster than atomic. And that’s why, basically everywhere we use property, we use nonatomic.
One more thing that you may have seen often in my tutorial is the code inside the dealloc function: self.xxx = nil; So you see here, now you see what this means? It is equivalent to [XXX release]; xxx = [nil retain]; If your property(nonatomic,retian) XXX is true, if it is not, it is true.
Because nil can send it any message without error. Why do we assign nil to release? I think you all have this coding habit when you use C.
int* arr = new int[10]; And then when it’s not in use, delete arr; arr = NULL; In objc you can say self.arr = nil; Get things done.
So much said, if you have any questions, welcome to leave a message below, I have time will be busy to reply to you. Have been reading my article friends, if you know the answer to help answer it, thank you first!
Next, I will translate Ray’s article on objC memory management and using property for memory management, so stay tuned!
———————————————————————————————————————— ————————————————————–
The syntax for declaring a property is:
@property (argument 1, argument 2) Type name;
Such as:
@property(nonatomic,retain) UIWindow *window;
Parameters are mainly divided into three categories:
Read and write properties: (readwrite /readonly)
Setter meaning :(assign /retain/copy)
Atomicity: (atomicity /nonatomic)
The meanings of each parameter are as follows:
readwrite
Generates setter\getter methods, which are readable and writable by default
readonly
It just produces simple getters, no setters.
assign
By default,setter methods assign values directly without performing a retain operation. The assign function simply assigns values to variables. Such as:
– (void)setFirstName:(NSString *)inValue
{
firstName = inValue;
}
retain
The setter method releases the old value and retains the new value. The assignment function generated by retain retains the passed arguments when assigning to the variable. Such as:
– (void)setFirstName:(NSString *)inValue
{
[firstName autorelease];
firstName = [inValue retain];
}
copy
Setter methods Copy, same as retain. Copy generates an accessor function that copies the incoming value to a member variable. Such as:
– (void)setFirstName:(NSString *)inValue
{
[firstName autorelease];
firstName = [inValue copy];
}
atomicity\
The default is atomic and thread-safe. Such as:
– (NSString *)firstName
{
[threadLock lock];
NSString *result = [[firstName retain] autorelease];
[threadLock unlock]; \
return result;
}
nonatomic
Non-thread-safe, variable protection, improved performance.
Such as:
– (NSString *)firstName
{
NSString *result = [[firstName retain] autorelease];
return result;
}
———————————————————————————————————————— ————————————————————–
Retain is not an NSString object with address 0×1111 and content @ “STR”. After the copy to another NSString, the address is 0×2222 and the contents are the same. The new object retains 1 and the old object remains unchanged. Retain to another NSString with the same address (create a pointer, copy the pointer) and the same contents, the retain value of this object is +1. That is, retain is a pointer copy and copy is a content copy. Bar *foo = [[Bar alloc] init]; // After executing this statement, foo has a retention count of 1.
[foo retain]; // After executing this statement, foo has a retention count of 2. [foo release]; // After executing this statement, foo has a retention count of 1.
Copy is a copy of something, and for things like NSString, that’s true. But what if the copy is an NSArray? For example, NSArray *array = [NSArray arrayWithObjects:@”hello”,@”world”,@”baby”]; NSArray *array2 = [array copy]; At this point, the system does create a chunk of memory for Array2, but it’s important to realize that each element in Array2 just copies a pointer to the corresponding element in array. This is known as “shallow copying “. It is important to understand this…. \
———————————————————————————————————————— —————————————————————
At sign property and at sign synthesize in pairs, automatically generating access methods for a class member variable. In Xcode4.5 and later, the @synthesize can be omitted.
Atomic and nonatomic Atomic: This property is available by default. The purpose of this property is to ensure that when the program is multi-threaded, the compiler will automatically generate some mutex lock code to avoid the problem of reading and writing this variable asynchronously. Nonatomic: If the object does not need to be multithreaded, add this property. This will allow the compiler to generate less mutex lock code and increase efficiency.
Readwrite: This property is the default and will automatically generate accessors for you. Readonly: Generates getters without setters. The real value of readwrite and readonly attributes is not to provide an interface to access member variables, but to control the access permissions of member variables.
3. Strong and weak strong: Strong references, also commonly referred to as references, directly determine the survival of the object pointed to. If there is no reference to an object and the object is no longer displayed in the list, the object is freed from memory. Weak: Weak reference, which does not determine the survival of the object. Even if an object holds numerous weak references, as long as no strong references point to it, it will still be removed. Strong and retain functions are similar; Weak is similar to assign, except that when the object disappears, weak automatically sets the pointer to nil.
4. Assign, copy, and retain assign: default values. Setter methods assign values directly without performing any retain operations or changing reference counts. Generally used to deal with basic data types. Retain: Release the old object, assign the value of the old object to the new object, and set the new object reference count to 1. Copy the original pointer, release the content of the object to which the original pointer points, and then set the pointer to point to the new object. Copy: The same as the retain process, release the old value and copy the new object. RetainCount is 1. A machine introduced to reduce dependency on context. I understand it as a copy of the content, ask for a space in memory, give it the original object content, make its reference count 1. Special attention should be paid to the copy property: objects defined with the copy property must comply with the NSCopying protocol and must implement the – (id)copyWithZone:(NSZone *)zone method. You can also use the assign command directly: Use copy for base data types (NSInteger, CGFloat) and C data types (int, float, double, char, and so on) : Retain for NSString: retain for other NSObject and its subclasses
Getter: specifies the name of the get method. Setter: specifies the name of the set call. In the @property property, if the property is a BOOL, usually we can use the getter to define a name we like, for example: @property (nonatomic, assign, getter=isValue) boolean value; @property (nonatomic, assign, setter=setIsValue) boolean value; \
Retain, copy, assign differences
1. Suppose you use malloc to allocate a block of memory and assign its address to pointer A. Later, you want pointer B to share the memory, so you assign A to POINTER B. In this case, a and B point to the same block of memory. When A no longer needs this block of memory, can it be released directly? The answer is no, because A does not know whether B is still using the memory block. If A frees the memory block, b will cause the program to crash when using the memory block.
2. Given the problem of assign in 1, how to solve it? The simplest way to do this is to use reference counting. In the same example above, we assign a reference count to that block of memory. When memory is allocated and assigned to A, the reference count is 1. The reference count increases to 2 when a is assigned to b. If A is no longer using the memory, it simply subtracts the reference count by one to indicate that it no longer owns the memory. B also decreases the reference count by one when it no longer uses the memory block. When the reference count goes to 0, the memory is no longer referenced by any Pointers, and the system can simply free it.
The differences between assign and retain are the same as those in retain. Assign is a direct assignment, which may cause problems in retain. When the data is of an int or float type, you can use assign. Retain uses a reference count, as described in 2. Retain causes the reference count to increase by 1 and release causes the reference count to decrease by 1. When the reference count reaches 0, the dealloc function is called and memory is reclaimed. 4. Copy is used when you do not want a and B to share the same memory. A and B each have their own memory.
Atomic and nonatomic are used to determine whether getters and setters generated by the compiler are atomic operations. In a multithreaded environment, atomic manipulation is necessary, otherwise incorrect results may be caused. With atomic, the setter function looks like this:
if (property ! = newValue) { [property release]; property = [newValue retain]; }
Two, a deeper understanding (including autoRelease)
1. Retain count + 1. Alloc, count is 1, release is going to call dealloc and destroy that object. If retain, release twice. Retain is usually required when assigning parameters to member variables in method. -(void)setName:(ClassName *) inputName {name = inputName; [name retain]; ClassName *myName = [[ClassName alloc] init]; [classA setName:myName]; //retain count == 2 [myName release]; Retain count==1, release name in ClassA dealloc will actually free memory.
2. Autorelease is much more tricky and its name is easy to confuse. I want to emphasize here: Autorelease is not garbage collection, and it’s nothing like Java or. GC in Net. Autorelease has nothing to do with scope! Autorelease principle: a. Create an AutoRelease pool B. Objects are generated from the autoRelease pool. C. Call the autoRelease function after the object is generated. This function simply marks the pool to remember torelease the object in the future. D. At the end of the program, the pool itself needs rerlease, in which case the pool releases each object marked as AutoRelease once. If an object retains count greater than 1 at this point, the object is still not destroyed. The example above would look like this: ClassName *myName = [[[ClassName alloc] init] autoRelease; // mark autorelease [classA setName:myName]; //retain count == 2 [myName release]; //retain count==1, note that the dealloc of ClassA cannot release name, otherwise the release pool will release the object with retain count 0, which is incorrect.
One thing to remember: if you’re alloc or new out of this object, you need to call release. If you use autorelease, release only once when a retain has occurred (leaving retain count always 1).
3. The new flag in Xcode is strong weak
Strong is used to modify strongly referenced attributes; Corresponding to previous retain
Weak is used to modify the attribute of a weak reference. Corresponds to the previous assign
Strong and weak are new object variable properties introduced by ARC. X code 4.2 (ios sdk4.3 and below) and previous versions use retain and assign, older versions do not support ARC. ARC was introduced after xcode 4.3 (ios5 and above) and strong and weak were used. Assign: Used for non-pointer variables. For basic data types (such as NSInteger) and C data types (int, float, double, char, etc.), as well as ids such as @property (nonatomic, assign) int number; @property (nonatomic, assign) id className; // The id must be assigned. Retain the pointer variable without an *. That is, you define a variable, and that variable can be changed as the program runs, affecting other methods. Generally used for strings (NSString, NSMutableString), arrays (NSMutableArray, NSArray), dictionary objects, view objects (UIView), controller objects (UIViewController), etc. For example: @property (nonatomic,retain) NSString * myString; @property (nonatomic, retain) UIView * myView; @property (nonatomic, retain) UIViewController * myViewController; Xcode 4.2 does not support ARC, so it will frequently use retain to modify and release when used, while Xcode 4.3 supports ARC and can use Retian. There is no need to manually release memory, the system will automatically do it for you. If you develop in xcode4.3 or later, Retain and strong are the same, there is no difference. @property(nonatomic,strong) MyClass *myObject; Property (nonatomic,retain) MyClass *myObject; @property(nonatomic, weak )id
delegate; @property(nonatomic,assign)id
delegate; At present, the attributes automatically generated by the system are all modified with weak. I think xcode 4.2 does not support ARC, so everyone uses retain. Now that xcode4.3 supports ARC, apple advised programmers to drop retain and use weak instead. Weak is the same as assign. In xcode4.3, you can also discard the use of assign and use weak instead. Unsafe_unretained: unsafe_unretained is the same as the same assignment across ios5. Because weak is used in ios5, you can’t use it in ios4.3, but if you change weak to unsafe_unretained, you can use it. The main reason is that pre-ios 5 systems used this property instead of weak. Copy: This is probably the hardest thing for most people to understand, and I don’t understand either. Retain is the same as retain. The only difference is that copy is only used for NSString and not for NSMutableString. But it seems like when a class inherits NSObject, the properties in that class need to use copy, for example: #import
#import
{ CLLocationCoordinate2D coordinate; NSString *title; NSString *subtitle; } @property (nonatomic) CLLocationCoordinate2D coordinate; @property (nonatomic, copy) NSString *title; @property (nonatomic, copy) NSString *subtitle; At sign end that’s what we’re going to use anyway. Just remember: xcode used retain and assign before 4.2; Xcode4.3 or later uses strong and weak. Xcode4.2 programmers used to use retain, so the code is retian. Newbie will use strong and weak if they learn xcode4.3. Readonly This tag indicates that the property is read-only. The default tag is read/write. If you specify read-only, you only need one reader in the @implementation. Or if you use the @synthesize keyword, there’s a reader method that gets parsed. And if you try to assign a value to a property using the dot operator, you will get a compilation error. Readwrite This flag indicates that the property is treated as read and write, which is the default property. Both the setter and the reader need to be implemented in the @implementation. If the @synthesize keyword is used, both the reader and setter are parsed. The assign tag indicates that the setter assigns values directly, which is also the default. In an application that uses garbage collection, if you want an attribute to use assign and the class complies with the NSCopying protocol, you should specify this tag instead of simply using the default, otherwise you’ll get a compile warning. Again, this tells the compiler that you really need to assign, even if it’s copiable. Retain specifies that retain will wake up the retain message for the incoming value on assignment. This property can only be used for Objective-C object types, not Core Foundation objects. Retain increases the reference count of an object, which is not present in either the basic datatypes or Core Foundation objects. Copy Indicates that a copy of the passed value is used when assigning a value. Copy is performed by the copy method, and this property is only valid for object types that implement the NSCopying protocol. For a more in-depth discussion, see the section “Copying”. Nonatomic indicates that accessors are not atomic operations, and by default, accessors are atomic operations. That is, in a multithreaded environment, the parsed accessor provides a secure access to the property, and the return value from the accessor or set value from the setter can be done in one go, even if it is being accessed by another thread. If you do not specify nonatomic, in a self-managed memory environment, the parsed accessor retains and automatically releases the returned value. If nonatomic is specified, the accessor simply returns the value. So the default property properties are readwrite, assign, atomic(without this keyword)\
———————————————————————————————————————— ——————————————————————————————-
1,assign :
Simple assignment without changing the index count
Suppose you allocate a block of memory using malloc and assign its address to pointer A. Then you assign a to POINTER B because you want pointer B to share this block of memory. In this case, a and B point to the same block of memory. When A no longer needs this block of memory, can it be released directly? The answer is no, because A does not know whether B is still using the memory block. If A frees the memory block, then B will crash the program while using the memory block
Application:
For basic data types (such as NSInteger, CGFloat) and C data types (int, float, double, char, etc.)
Applies to simple data types
\
2, retain:
In contrast to strong, reference counting is used, retain+1, release-1; When the reference count is 0, dealloc is called and memory is freed \
\
3, the copy:
For unshared memory, each pointer has its own memory space \
\
4, Atomic // default property
A, when A variable is declared atomic, it means that only one thread in multiple threads can access it
B, when a variable is declared atomic, it is thread-safe but affects access speed.
C, when a variable is declared atomic, access locks need to be set to ensure that the variable gets/sets correctly under non-ARC compilations
5, nonatomic
A, when A variable is declared nonatomic, it means that multiple threads can access it at the same time
B) when a variable is declared as nonatomic, it is not thread-safe and is fast to access;
C) when a variable is declared nonatomic, it can get out of control when accessed by two different threads. \
Summary: Atomic and nonatomic are used to determine whether getters and setters generated by the compiler are atomic operations. In a multithreaded environment, atomic manipulation is necessary, otherwise incorrect results may be caused. With atomic, the setter function looks like this:
if (property ! = newValue) {
[property release];
property = [newValue retain];
}
6. Strong :// Default property in ARC, equal to retain in non-ARC
Corresponding to retain,
Application Scenarios:
The strong property is used in ARC
@property (strong,nonatomic) ViewController *viewController; //strong for the main window
7,weak:
Corresponding to assign,
Application Scenarios:
IBOutlets, for example, a subclass of UIViewController, a generic control.
@property (weak, nonatomic) IBOutlet UIButton *myButton; //weak for child controls
The child control uses the weak pointer because it already has a strong pointer to it on the window. So all you need is a weak pointer. IBOutlet is a type that has no concrete content, but Xcode is used to keep track of which property is an Outlet. The compiler ignores it, there’s nothing there. If strong is released, the weak will be nil. If strong is released, the weak will be nil. \
Strong and weak
Premise:
We compare the strong or weak object to a kite. The kite wants to fly free from the string. If there is a string, the kite cannot break free
Process analysis
Variable of the strong property:
When we declare a variable pointing to a kite as strong, then you have the string that controls the kite. If five people control the kite at the same time (i.e., the kite object has three strong variables pointing to it), then there is only one condition in which the kite will break free from the string drop: All three of them released their wires.
The weak variable:
Point when we put a kite in the variable declaration is weak, at the moment, just like standing by the audience see a kite, when the above three people also hold down the line, they only see a kite, and can’t control it, they can do is use finger pointing to the kite, and shouted, “look, the kite fly so high!” Handle, however, when the above three are off the line, at this point, the kite flew away, out of sight, no matter how much the audience, they would never see the kite, the story tells us a truth: when the strong type of pointer is released, after all the weak point to the same object pointer will be reset.
\
8, readonly
There is only a get method, not a set method
\
Readwrite // Default property
Get/set methods
\
10,unsafe_unretauined
Used in ARC compilation environments, similar to assign in this environment. It simply tells ARC how to correctly call retain and release variables declared as unsafe_UNREtauined
\