1. assign意味着直接赋值,retain意味着release旧值,retain新值
1.1 @property (assign, nonatomic) UIWindow *window;
意味着:
- (void )setWindow:(UIWindow *)window
{
_window = window;
}
// AppDelegate.m
// 因为是assign,所以不会对[[UIWindow alloc]init]产生的对象做retain操作. 在自动释放池释放时,引用计数器会由1变成0,AppDelegate不能长期拥有该Window
self.window = [[[UIWindow alloc]init]autorelease];
//既然自动释放池释放时,会把产生的Window销毁,不添加autorelease呢?这样不符合内存管理原则,这么做意味着,产生的Window永远无法销毁
self.window.backgroundColor = [UIColor redColor];
self.window.frame = [UIScreen mainScreen].bounds;
[self.window makeKeyAndVisible];
return YES;
// 如果用下面修改上面的代码为下面这样,貌似AppDelegate既可以长期拥有Window,AppDelegate释放时,也可以销毁Window
self.window = [[UIWindow alloc]init];
// 潜在问题是,如果对self.window重复赋值,例如再写一行代码 self.window = [[UIWindow alloc]init]. AppDelegate释放时,就无法销毁旧的Window
self.window.backgroundColor = [UIColor redColor];
self.window.frame = [UIScreen mainScreen].bounds;
[self.window makeKeyAndVisible];
return YES;
- (void)dealloc{
[self.window release];
[super dealloc];
}
1.2 @property (retain, nonatomic) UIWindow *window;
意味着:
- (void )setWindow:(UIWindow *)window
{
if (_window != window) {
[_window release];
_window = [window retain];
}
}
// AppDelegate.m
// 因为是retain,所以会对[[UIWindow alloc]init]产生的对象做retain,在自动释放池释放时,会由2变成1,AppDelegate可以长期拥有该Window
self.window = [[[UIWindow alloc]init]autorelease];
self.window.backgroundColor = [UIColor redColor];
self.window.frame = [UIScreen mainScreen].bounds;
[self.window makeKeyAndVisible];
return YES;
// 为了防止内存泄露,在AppDelegte销毁的时候,要对拥有的window做release操作
- (void)dealloc{
[self.window release];
[super dealloc];
}
2.非ARC内存管理的由来
2.1 准备:
-------------Dog----------Begin-------------
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@end
#import "Dog.h"
@implementation Dog
- (void)dealloc
{
NSLog(@"Dog--dealloc");
[super dealloc];
}
@end
-------------Dog----------End-------------
-------------Person----------Begin-------------
#import <Foundation/Foundation.h>
@class Dog;
@interface Person : NSObject
{
Dog *_dog;
}
- (void)setDog:(Dog *)dog;
- (Dog *)dog;
@end
#import "Person.h"
@implementation Person
- (void)setDog:(Dog *)dog
{
_dog = dog;
}
- (Dog *)dog
{
return _dog;
}
- (void)dealloc
{
NSLog(@"Person--dealloc");
[super dealloc];
}
@end
-------------Person----------End-------------
2.2 原始版本
-------------MainViewController----------Begin-------------
Dog *d = [[Dog alloc]init];
Person *p =[[Person alloc]init];
p.dog = d;
[d release];
NSLog(@"p.dog----%@",p.dog); //僵尸对象
[p release];
-------------MainViewController----------End-------------
2.3 优化,解决僵尸对象的问题
修改Person的Set方法
- (void)setDog:(Dog *)dog
{
_dog = [dog retain]; // 这样MainViewController就不会访问僵尸对象
}
- (void)dealloc
{
NSLog(@"Person--dealloc");
[self.dog release]; //谁retain,谁release
[super dealloc];
}
2.4 存在的问题:重复赋值时,Person销毁时,只能释放最新持有的Dog,旧Dog内存泄露
Dog *d = [[Dog alloc]init];
Dog *d2 = [[Dog alloc]init];
Person *p =[[Person alloc]init];
p.dog = d;
p.dog = d2;
[d release];
NSLog(@"p.dog----%@",p.dog);
[p release];
2.5 优化:解决重复赋值的问题
- (void)setDog:(Dog *)dog
{
[_dog release];
_dog = [dog retain];
}
2.6 存在的问题:重复赋值同一条狗,会出现野指针错误
Dog *d = [[Dog alloc]init];
Person *p =[[Person alloc]init];
p.dog = d;
p.dog = d; // 执行到这一行时,会出现野指针错误
[d release];
NSLog(@"p.dog----%@",p.dog);
[p release];
2.7 优化:在set方法加判断
- (void)setDog:(Dog *)dog
{
if (_dog != dog) {
[_dog release];
_dog = [dog retain];
}
}
3. 属性用retain相当于生成了2.6优化之后set/get方法;如果用assign,2.6优化之后的set方法还的写上,这样对象才能长期持有该属性
3.1 修改person.h
@interface Person : NSObject
@property (retain,nonatomic) Dog *dog;
@end
3.2 修改person.m,dog的set方法和get可以去掉了
4. 总结,做非ARC开发
1>要长期持有一个属性用retain. 注:一般情况,属性除了UI控件,一般都是想长期持有的
2>在dealloc方法里,要释放:
写法一:[self.属性名 release];
_属性名 = nil;
写法二:[_属性名 release];
_属性名 = nil;
写法三:[self.属性名 nil];
5.