iOS MRC开发

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. 

原文地址:https://www.cnblogs.com/oumygade/p/4281367.html