• Objective-C 【This is ARC】


    ———————————————————————————————————————————
    ARC的概念及原理

    (1)指针分类

    强指针:默认情况下,所有的指针都是强指针,关键字strong

    弱指针:_ _weak 关键字修饰的指针。

    声明一个弱指针如下:

    _ _weak Person *p;  (注意:这里的weak前面是两个下划线,且两个下划线之间没有空格!)


    (2)ARC

    Automatic Reference Counting,自动引用计数。

    在工程中十分的简单,和往常一样编写代码就好,只不过永远不写retain、release和autorelease就好!这也是ARC基本原则。


    (3)ARC工作原理及判断准则

    工作原理:   ARC是OC编译器的特性,而不是运行时特性或者垃圾回收机制,ARC所做的只不过是在代码编译时为你自动在合适的位置插入release或者autorelease。

    判断准则:   (只要没有强指针指向对象,对象就会被释放)
    当使用ARC的时候,我们要暂时忘记“引用计数器”,因为判断标准变了。(标准不再是retainCount是否为0,而是有没有强指针指向)



    ★注意:

    对于强指针指向的对象,一旦强指针指向了别处,那么对象内存空间就被释放。

    如果对象同时被一个强指针和一个弱指针指向,强指针一旦指向别处,那么对象内存空间也会释放,而指向该对象的弱指针被赋值nil。(这句话告诉我们,强指针指向对象并持有该对象,而弱指针指向对象却不持有该对象)


    代码:

    #import <Foundation/Foundation.h>

    @interface Car : NSObject
    -(void)run;
    @end

    @implementation Car
    -(void)run
    {
        NSLog(@"Car run!");
    }

    - (void)dealloc
    {
        NSLog(@"Car dealloc!");
    }
    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
    //        在iOS5以后,默认的都是ARC机制
    //        ARC不能使用release、autorelease、retainCount和retain
    //        ARC写允许重写dealloc方法,但是不能调用 [super dealloc];
            
            Car *car1=[[Car alloc]init];
            [car1 run];
        }//执行完这句话car1的内存空间释放
        NSLog(@"123456789");
        return 0;
    }


    ———————————————————————————————————————————
    ARC下 单对象的内存管理

    代码:

    #import <Foundation/Foundation.h>

    @interface Car : NSObject
    @property int speed;
    -(void)run;
    @end

    @implementation Car
    -(void)run
    {
        NSLog(@"Car run!");
    }

    - (void)dealloc
    {
        NSLog(@"Car dealloc!");
    }
    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
    //        Car *car=[[Car alloc]init];
    //        
    //        car=nil;
    ////        car在指向nil的时候是会被立即释放的,因为car被赋值nil,原来在堆区中car指向的内存空间没有了强指针的指向,所以内存释放。
    ////       因为car被设置为了nil,所以下面两行相当于是对nil进行的操作 nil.speed=12; ,但是对nil的操作是可行的却没变化的,所以输出的值car.speed还是0
    //        car.speed=12;
    //        NSLog(@"car.speed=%d",car.speed);
            
            
    //        car1 和 car2 指向的是同一个内存空间
    //        __strong Car *car1=[[Car alloc]init];//强指针也是可以加上 __strong 来显性修饰的
    //        
    //        __weak Car *car2=car1;
    //        
    //        car2=nil;//弱指针car2被赋值为nil,但是强指针car1仍指向原内存空间,所以说在执行完 car2=nil; 之后,原内存空间并不会被释放。
    //        
    //        car1=nil;//强指针car1被赋值为nil,那么原内存空间会在语句 car1=nil; 执行完后立即释放
    //        
    //        NSLog(@"**********");



    //        注意:
    //        ①:
    //        __weak Car *car3=[[Car alloc]init];
    //        __strong Car *car4=car3;
    //        如果是这种写法,一开始在声明car3的时候就没有强指针指向,那么声明完car3之后内存立即释放(这句话也是完全没有意义的!)
            
    //        ②:
    //        __strong Car *car5=[[Car alloc]init];
    //        __strong Car *car6=car5;
            
    //        car5=nil;
    //        NSLog(@"***********");
    //        如果是两个强指针指向同一个内存区域,car5赋值nil之后,car6还指向原内存地址,所以内存并没有释放,而是在自动释放池大括号结束时释放        
        }
        return 0;
    }


    ———————————————————————————————————————————
    ARC下 多对象内存管理

    这个地方没有什么好说的,如果在程序中一个实例对象中的实例变量是另一个类型的实例对象,那么我们应该将他设置成强指针类型,因为我们要用到他,用它的时候不能让他成为nil。

    设置变量的时候我们可以:

    @property (nonatomic,strong) Dog *dog;  //当然这里是默认的

    还有就是用@property增强来设置实例变量的时候
    (下面等同)
    strong —————retain
    weak—————assign


    ———————————————————————————————————————————
    ARC下 循环引用问题

    代码:

    Dog.h

    #import <Foundation/Foundation.h>
    @class Person;

    @interface Dog : NSObject
    @property(nonatomic,strong)Person *owner;
    @end


    Dog.m

    #import "Dog.h"

    @implementation Dog
    - (void)dealloc
    {
        NSLog(@"Dog dealloc!");
    }
    @end


    Person.h

    #import <Foundation/Foundation.h>
    @class Dog;

    @interface Person : NSObject
    @property(nonatomic,weak)Dog *dog;
    @end


    Person.m

    #import "Person.h"

    @implementation Person
    - (void)dealloc
    {
        NSLog(@"Person dealloc!");
    }
    @end


    main.m

    #import <Foundation/Foundation.h>
    #import "Person.h"
    #import "Dog.h"

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Person *p=[[Person alloc]init];
            
            Dog *dog=[[Dog alloc]init];
            
    //        不加下面两句话的时候(没有互相建立关系的时候),他们是可以释放的。但是他们之间一旦有了关系,就无法被释放(两个都是strong类型)
            p.dog=dog;
            
            dog.owner=p;
    //        想要解决这个问题,其实和前面在MRC机制下差不多,我们只需要将他们两个其中一个的类型设置为weak,这样就可以解决循环调用的问题了。
    //        比如我们将Person 中的Dog类型的参数设置为weak,那么他就会先释放,然后dog的owner参数也会释放,这样两个都能释放了
        }
        return 0;
    }


    附加:ARC下 的 @property 参数

    ARC中的 @property

    strong:用于OC对象,相当于MRC中的retain
    weak:用于OC对象,相当于MRC中的assign(在定义@property类型的时候就不要加两个下划线了)
    assign:用于基本数据类型,跟MRC中的assign一样
    copy:用于NSString,跟MRC中的copy一样

    ★在ARC下解决循环引用问题,一边用strong,一边用weak


    ———————————————————————————————————————————
    ARC的兼容和转换

    ①如何在ARC文件中兼容非ARC的文件




    步骤就在上图了,Dog类是ARC,Car类是非ARC。那么我们就找到Car类的Compiler Flags,然后双击在里面键入 -fno-objc-arc  如下图(如果是-f-objc-arc就是兼容ARC)




    ②如何将MRC文件转换成ARC文件

    首先确保你要转换的文件之前是一个MRC文件,也就是将ARC的开关关闭





    然后按照下图的操作,先选定该target,然后Edit,然后Convert,然后To Objective-C ARC…






    最后按照提示下一步,你就会发现,你的代码发生了一些改变:





    这就是将MRC文件转换成ARC文件的方法。但是,注意,这种方法不一定100%成功,可能会转换错误,所以用的时候要谨慎!


    ———————————————————————————————————————————

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    原创 ios绘制 圆形气泡
    ios 线程安全单例写法
    (转)ios中点击地图控件MKMapView的某点获取该点的经纬度
    使用正则提取url(iOS)
    MAC系统崩溃,使用命令行复制硬盘内容
    UISearchBar控件UI操作
    app发布流程详解
    App Store审核指南(中文版)2010版
    GCD详解
    iOS扫描二维码(系统方法)
  • 原文地址:https://www.cnblogs.com/wzy294250051/p/4787879.html
Copyright © 2020-2023  润新知