首页 > 技术文章 > OC进阶(二)

iosnds 2015-10-28 14:21 原文

1.autorelease注意及错误用法

#import <Foundation/Foundation.h>
#import "Person.h"
/**
 *  autorelease的使用注意
 */
void test(){

    //1 自动释放池
    Person *p = [Person new];
    @autoreleasepool {
        
        //autorelease的使用注意:
        // 1)并不是所有的放到自动释放池中的代码,产生的对象就会自动释放
        //   如果需要释放,必须加入到自动释放池
        //        Person *p = [[Person new] autorelease];
        
        //我们只需要在自动释放池代码块中调用autorelease 就可以把对象
        //加入到自动释放池
        [p autorelease];
        
    }
    
    //2) 如果对象调用了autorelease 但是,调用autorelease的时候,没有在任何一个自动释放池中,此时该对象也不会 被加入到自动释放池
    //    Person *p = [[Person new] autorelease];


}

/**
 *  自动释放池的嵌套
 */
void test2(){

    Person *p = [[Person alloc] init];
    
    [p retain];  //2
    //autoreleasepool的嵌套
    //自动释放池的栈结构(数据结构),和内存的栈区是不一样的
    // 对象存在 位于栈顶位置的自动释放池中
    @autoreleasepool {
        
        @autoreleasepool {
            
            @autoreleasepool {
                
                [p autorelease];  //20M
                
                for(int i=0;i<10000;i++){
                    
                    Person *temp = [[Person new] autorelease];
                    
                    
                }
                
                
                //1000行
                
                
                
                
            }// [p release];  //1
            
            [p autorelease];
            
        }//
        
    }

}
int main(int argc, const char * argv[]) {
    
    Person *p = [[Person alloc] init];   //1
   
    //autoreleasepool的嵌套
    //自动释放池的栈结构(数据结构),和内存的栈区是不一样的
    // 对象存在 位于栈顶位置的自动释放池中
    @autoreleasepool {
        
        
        [p autorelease];
        
    }//   [p release];    1---->0
    
    [p release]; //错误的用法
    
    
    return 0;
}

2.autorelease的应用场景

+(instancetype)person{
    //Person person  ---> Person
    //Stduent person ----> Student
    //创建对象
    return [[[self alloc] init] autorelease];  //返回的时对象的空间
    //能够帮我们把对象给加入到自动释放池

}


        //帮我们快速的创建对象,并且管理对象的内存(加入到自动释放池)
//        Person *p = [Person person];
        // 1) 创建一个对象  p
        // 2) 用完之后,系统把对象释放掉 p

3.ARC机制

/*
 
   ARC机制
 
    1) 判断是否是ARC机制
   
       查看项目信息   不能使用retain release autorelease retainCount
       在dealloc方法中不能使用 [super dealloc];
 
    2) 使用
 
       正常创建对象,不用手动释放对象
 
 */


#import <Foundation/Foundation.h>
#import "Dog.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //ARC机制下对象的释放
        Dog *jd = [Dog new];
        [jd run];
        
        
    }
    return 0;
}

4.ARC单对象内存管理

#import <Foundation/Foundation.h>
#import "Car.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //在ARC下对象释放的判断依据: 对象没有强指针指向
        //对象会立即释放内存空间
        // bigBen 强指针(指针默认的都是强指针)
        Car *bigBen = [Car new];
        //定义另外一个强指针指向
        //__strong 修饰符,修饰这个指针是一个强指针,也可以不写
        //__weak         修饰的这个指针是若指针
//        __strong Car *bmw = bigBen;
        __weak Car *bwm2 = bigBen;
        NSLog(@"bigBen = %@,bwm2 = %@",bigBen,bwm2);
        //bigBen的指向发生改变,对于Car对象来说没有强指针指向了,所以要释放对象
        
        bigBen = nil;  //
        // 要   1) bigBen 是强指针,重新指向其他内容了,对于对象来说没有强指针了
        //      2) 弱指针 赋值为nil
        
        NSLog(@"bigBen = %@,bwm2 = %@",bigBen,bwm2);
        [bwm2 run];  //[nil run];
        
        [bigBen run]; //[nil run];
        
        NSLog(@"xxxxxx");
        
    }
    return 0;
}

5.ARC多对象内存管理

int main(int argc, const char * argv[]) {
    @autoreleasepool {
    
        //
        Dog *byd = [Dog new];
        
        Person *p = [Person new];
        
        p.dog = byd;
        
//      1)在 @property (nonatomic,weak) Dog *dog;
//        byd = nil    // Dog对象会立即释放
//                     因为该对象没有强指针指向了
        
//      2)在 @property (nonatomic,strong) Dog *dog;
//        byd = nil    // Dog对象不会被立即释放
//
        byd = nil;
        
        
        
    }
    return 0;
}

6.ARC下循环引用问题

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        //dog p 都是局部变量
        //局部变量的生命周期: 从定义的位置开始,到它所在的代码块"}"结束
        Dog *dog = [Dog new];
        Person *p = [Person new];
        
        //构成一个循环引用
        p.dog = dog;  //_dog weak类型
        dog.owner = p;
        
        NSLog(@"xxxxx");
        
    }
    return 0;
}

7.分类

/*
   
    分类: 
  
        一些方法的声明和实现
 
    作用: 在不修改类的源代码的前提下,给类增加新的功能
  
    使用步骤:
 
         //此处是声明一个类
         @interface Person : NSObject
 
         @end
 
         //类的实现
         @implementation Person
 
 
         @end
 
 
       1) 声明一个分类
 
          格式:
 
          @interface 待扩展的类名 (分类的名称)
 
          @end
 
          Person+base  -->分类文件的命名规则
          eat run
 
          如:
          @interface Person (base)
            //吃
             -(void)eat;
            //跑
             -(void)run;
          @end
 

 
       2) 实现这个分类
 
          格式:
 
          @implementation 待扩展的类 (分类的名称)
  
          @end
 
          如:
 
          Person+base 类别实现
          @implementation Person (base)
             //吃
             -(void)eat{
             
                NSLog(@"人会吃东西");
             }
             //跑
             -(void)run{
             
                NSLog(@"人会跑");
             
             }

          @end
 
 
 
       3) 使用分类中的方法
 
          和使用类中原有的对象一样
          Person *p = [Person new];
          [p xxx];
 
 
 
 
         playGame类别  --- 张三
         playlol  playdota
   
 
         study 类别    --- 李四
         studyc   studyios
 
 */
/*
 
    分类的使用注意事项:
 
    1) 在分类的声明中不能声明实例变量
 
        不能定义实例变量 也不能使用 @property
 
    2) 在分类的方法中,可以访问类中的实例变量
 
 
    3) 在分类中存在和类同名的方法
 
       优先访问的时 分类中 的方法
 
    4) 当在多个类别中有同名的方法的时候,这时候,执行的最后编译的那个类别的同名方法
 
       分类的 > 原类
 
       最后编译的分类 >  其他的分类 
 */
#import "Person.h"

@interface Person (playGame)
//增加一个类别,类别名称 playGame 给Person增加新的方法
-(void)playLol;
-(void)playDota;
@end
#import "Person+playGame.h"

@implementation Person (playGame)
-(void)playLol{
    
    NSLog(@"那人正在玩撸啊撸");

}
-(void)playDota{

    NSLog(@"那人正在玩刀塔");

}
@end

8.类扩展

#import "Person.h"
#import "Person_work.h"
//扩展\延展\延展分类
//延展是一个特殊的分类
//特点:
// 1) 可以在延展中 定义实例变量
// 2) 不能使用 @implementation 类名() 实现类别的方法
// 3) 作用,可以定义私有的变量和方法
@interface Person ()
{
    float _weight;
}
-(void)run;  //run 相对私有的方法
@end


@implementation Person
-(void)run{

    NSLog(@"延展的run方法 %.2f",_weight);

}
// Person_work.h 声明的,延展
-(void)work{

    NSLog(@"work %d",_height);

}
-(void)test{

    [self run];
    [self work];
}
@end

 

推荐阅读