How to avoid memory leaks caused by circular references:
Take delegate mode as an example (Viewcontroller and view are proxy modes, Viewcontroller have View rights, Viewcontroller are also agents of view (handling events in view):
- UserWebService.h
- #import
- Defines a WS-completed delegate
- @protocol wscompletedelegate
- @required
- -(void) finished;//the method to be implemented
- @end
- @interface Userwebservice:nsobject
- {
- ID delegate;//an ID type of dategate object
- }
- @property (assign) ID delegate;
- -(ID) Initwithuserdata: (user *) user;
- -(void) connectiondidfinishloading: (nsurlconnection *) connection;
- @end
- USERWEBSERVICE.M:
- #import
- @systhesize delegate;//Synchronize this delegate object
- @implementation Userwebservice
- -(void) connectiondidfinishloading: (nsurlconnection *) connection
- {
- [Delegate finished]
- }
- @end
LoginViewController.h:
- #import "UserWebService.h"//contains the header file containing the delegate
- @interface Loginviewcontroller:uiviewcontroller
- -(void) submit;
- @end
- LOGINVIEWCONTROLLER.M:
- @implementation Loginviewcontroller
- -(void) Submit
- {
- User *user = [[user Alloc]init];
- [User setuserid:@ "username"];
- [User setpassword:@ "password"];
- WS = [[Userwebservice alloc] initwithuserdata:user];
- Ws.delegate = self;//Set the listener for the delegate
- [User release];
- [WS-Send];
- }
- Implement the methods in the delegate,
- -(void) finished
- {
- Nsattry *users = [ws users];
- }
- @end
As you can see, delegate is declared as assign:
- @property (assign) ID delegate;
Copy Code
What happens if the declaration is retain?
- Loginviewcontroller Alloc a userwebservice,userwebservice agent is loginviewcontroller, so the circular reference:
- WS = [[Userwebservice alloc] initwithuserdata:user]; Userwebservice object reference count plus 1
- Ws.delegate = Self;//loginviewcontroller Object reference count plus 1
After the external frame Allocloginviewcontroller object, the reference count of the Loginviewcontroller object is 2, and after release it cannot be destroyed, resulting in a memory leak
So using assign instead of retain to declare attributes avoids circular references, and arc can be resolved with weak references
Memory detection can be inherited by Xcode with the Instrument tool, but the memory leaks caused by circular references are undetectable.
Object release to a reference count of 0, if the corresponding pointer is not assigned to nil, how to appear the wild pointer
- ClassA *a = [[ClassA alloc] init];
A = Nil;//alloc Memory no object can control it, the reference count is always 1, which creates a memory leak
A simple assignment operation does not alter the object's reference count:
- ClassA *a = [[ClassA alloc] init];
- ClassA *b = reference count or 1 for objects pointed to by a;//a and b
@property:
The default is @property to @property (atomic,assign)
Nonatomic: There is no corresponding atomic keyword, even if the above is written, but atomic just is the default when you do not declare this feature, you cannot take the initiative to declare this feature. Nonatomic does not support multi-threaded access, atomic has a synchronization mechanism, support multi-threaded access, if you need multi-threaded access, declared as atomic (maintain the default), otherwise declared as nonatomic, because nonatomic efficiency is much higher than atomic
About assign, retain, and copy:assign are the system default property attributes, which apply almost all variable types to OC. For variables of non-object type, assign is the only optional attribute. But if you declare a variable of an object type as assign under the reference count, you will receive a warning from the compiler at compile time. Because assign for the object attribute under reference count, just creates a weak reference (that is, a shallow copy of what is usually said). Returning samples using variables can be dangerous. When you release the previous object, the assigned object pointer becomes a headless pointer. Therefore, when declaring a property for a variable of an object type, use assign as little as possible (or not).
About the setter of the assign synthesis, it looks like this:
- -(void) Setobja: (ClassA *) a {
- Obja = A;
- }
Before delving into the retain, write the setter that declares the Retain attribute:
- -(void) Setobja: (ClassA *) A
- {
- If (Obja! = a)
- {
- [Obja release];
- Obja = A;
- [Obja retain]; Retain count plus 1 for objects
- }
- }
Obviously, in the retain setter, the variable retain once, so even if you self.obja in the program = A; Only this sentence, Obja still need to release, in order to ensure that the object retain count is correct. But if your code obja = A; Just wrote such a sentence, so here is just a shallow copy, the object's retain count does not increase, so write, you do not need to release obja in the back. The difference between the 2 sentences is that the first sentence uses the compiler-generated setter to set the value of the Obja, while the second sentence just is a simple pointer assignment
- NSString *str = [[NSString alloc] initwithstring @ "abc"];
- str = @ "ABCD"; '
- [STR release];
- NSLog ("%@", str);//Print out ABCD
Why didn't str become a wild pointer? Because string constants (including NSString and @ "...") have a large reference count (100k+), which is essentially not released (managed by OC itself), so string constants can be used without release
IOS Circular Reference Delegate (instance description)