zoukankan      html  css  js  c++  java
  • ARC学习笔记(一)

    综述:

    在项目中使用 ARC之后,所有的编程都和以前一样,除了你不再调用 retain, release, autorelease。启用 ARC 之后,编译器会自动在适当的地方插入retain, release, autorelease 语句。

    ARC 的规则:

    只要还有一个变量指向对象,对象就会保存在内存中。

    ARC 的限制:

    ARC 只能工作于 Objective-C 对象,如果 应用使用了 Core Foundation 或 malloc()/free(),此时需要你来管理内 存。

    “strong”指针和“weak”指针:

    “strong”指针:能够保持对象的生命。

    因为 strong 指针会保持对象的生命,某些情况下你需要手动设置这些指针为 nil,否则可能导致应用内存不足。

    (默认所有实例变量和本地变量都是 strong 类型的指针,一般strong 变量不加 __strong 修饰。)

    “weak”指针:weak 变量仍然指向一个对象,但不是对象的拥有者,“weak”指针所指内容被释放时,“weak”指针会被自动置为nil.

    典型的例子是 delegate 模式:

    (你的ViewController通过strong指针拥有一个UITableView, TableView 的 data source 和 delegate 都是weak指针,指向ViewController)。

    对象之间的关联:

    启用ARC之后,不再需要考虑什么时候 retain 或 release 对象。唯一需要考虑的是对象之间的关联,谁拥有该对象,以及这个对象需要存活多久。

    一个例子:

    以下代码在 ARC 之前是不可能的,在手动内存管理中,从 Array 中 移除一个对象会使对象不可用,对象不属于Array 时会立即被释放。随后 NSLog()打印该对象就会导致应用崩溃。

    id obj =[array objectAtIndex:0];

    [array removeObjectAtIndex:0];

    NSLog(@"%@", obj);

    在ARC 中,这段代码是完全合法的,因为 obj 变量是一个 strong 指针, 它成为了对象的拥有者,从 Array 中移除该对象也不会导致对象被释放。

    ARC 的迁移:

    要启用一个项目的 ARC,你有以下几种选择:

    1. Xcode 带了一个自动转换工具,可以迁移源代码至 ARC


    2. 你可以手动转换源文件


    3. 你可以在 Xcode 中禁用某些文件使用 ARC,这点对于第三方库非常有用。

    Xcode 的自动迁移工具:

    1, ARC 是 LLVM3.0编译器的特性,而现有工程可能使用老的 GCC4.2 或 LLVM-GCC编译器,因此首先需要设置使LLVM 3.0 编译器。

    Project Settings -> target -> Build Settings,在搜索框中输入 compiler, 就可以列出编译器选项设置:

    另外最好也选上 Warnings 中的 Other Warning Flags 为 -Wall,这样编译 器就会检查所有可能的警告,有助于我们避免潜在的问题。

    同样,Build Options 下面的 Run Static Analyzer 选项也最好启用,这样 每次 Xcode 编译项目时,都会运行静态代码分析工具来检查我们的代码。

    2,  Build Settings 下面,选择“All”,搜索框输入"automatic",可以设置 "Objective-C Automatic Reference Counting"选项为 Yes,不过 Xcode 自动转 换工具会自动设置这个选项。

    3,  Xcode 的 ARC 自动转换工具: Edit->Refactor->Convert to Objective-C ARC

    4,  选择需要转换的文件,Xcode 可能会提示项目不能转换为 ARC。此时:

    打开 Xcode Preferences 窗口,选择 General 标签,启用 Continue building after errors 选项,再次执行 EditRefactorConvert to Objective-C ARC:

    5,        再有错误的情况下,就需要手工修改某些源代码。

    注意:Xcode 的自动转换工具最好只使用一次。多次使用可能会出现比较诡异的问题。假如你第一次转换没有转换所有的文件,当你稍后试图再次转换剩余的 文件时,Xcode 实际上不会执行任何转换操作。因此最好一次就完成转换,没有 转换的文件可以考虑手工进行修改。

    禁止某些文件的ARC:

    最简单的方法是直接使用 Xcode 的 ARC 转换工具,取消选中那些不希望 进行ARC转换的源文件,这样Xcode会自动对这些文件设置 -fno-objc-arc标 志。

    手动修改:对于某些我们不希望使用 ARC 的文件,例如第三方库源文件,可以在 Project Settings -> Build Phases 中,对这些文件选中 -fno-objc-arc 标志。

    另外,可以使用预处理指令在必要时保持与 ARC 兼容:

    #if _has_feature(objc_arc)

      //do your ARC thing here

    #endif

      或者假如你还想支持老的 GCC compiler:

    #if defined(_has_feature )&& _has_feature(objc_arc)

      //do your ARC thing here

    #endif

    ARC 自动迁移的常见问题:

    1,"Switch case is in protected scope"

    switch (x)

    {

    case Y:

      NSString *s =…;

      Break;

    }

    ARC 不允许这样的代码,指针变量需要定义在 switch 语句外面,或者使用{}定义一个新的块:

    switch (x)

    {

    case Y:

    {

      NSString *s =…;

      Break;

    }

    }

    这样 ARC 才能确定变量的作用域,从而在适当的时候释放该变量。

    2,"ARC forbids Objective-C objects in structs or unions"

    使用 ARC 之后,C Struct 中不能使用 Objective-C 对象, 解决办法是定义一个 Objective-C 类,不使用 C Struct。

    Property总结:

    • strong:等同于"retain",属性成为对象的拥有者
    • weak:属性是 weak pointer,当对象释放时会自动设置为 nil,记住 Outlet 
应该使用 Weak
    • unsafe_unretained:等同于之前的"assign",只有 iOS 4 才应该使用。

    (unsafe_unretained 指针和 weak 指针不一样的是,当相关联的对象释放时, 指针不会被设置为 nil,因此它实际上指向不存在的对象。)

    dealloc 方法:

    启用 ARC 之后,dealloc 方法在大部分时候都不再需要了。如果你的 dealloc 方法处理了其它资源(非内存)的释放,如定时器、Core Foundation 对象,则你仍然需要在 dealloc 方法中进行手动释放,如 CFRelease(), free()等。

    Toll-Free Bridging:

    当你在 Objective-C 和 Core Foundation 对象之间进行转换时,就需要使用 Bridge cast。(比如CFStringRef与NSString)

    • 使用 CFBridgingRelease(),从 Core Foundation 传递所有权给 Objective-C;
    • 使用 CFBridgingRetain(),从 Objective-C 传递所有权给 Core Foundation;
    • 使用__brideg,表示临时使用某种类型,不改变对象的所有权。

    iOS 4 中使用 ARC:

    ARC 主要是 LLVM 3.0 编译器(而不是 iOS 5)的新特性,因此你也可以在 iOS 4.0之后的系统中使用ARC,不过需要注意的是,weak 指针需要iOS5才能使用。 如果你要在 iOS 4 中部署 ARC 应用,你就不能使用 weak property 和__weak 变 量。

    ARC 高级指南:

    1,Blocks 与 ARC。(指南里面用了很大的篇幅讲解)

    2,Singleton 与 ARC。

    3,Cocos2D 和 Box2D。

    4,Autorelease 和 AutoreleasePool。

    ARC 仍然保留了 AutoreleasePool,但是采用了新的 Block 语法:@autoreleasepool.

    在 ARC 中,方法名如果以 alloc, init, new, copy, mutableCopy 开头,就是返回 retain 的对象,其它方法全部返回 autorelease 的对象。这条规则实际 上与手动内存管理是一样的。

    autorelease 对象则是在 autorelease pool 排干( drain ) 时才会被释放。在 ARC 之前,你需要调用 NSAutoreleasePool 对象的 [drain] 或 [release] 方法,现在则是直接在 @autoreleasepool 块退出时进行 drain:

    @autoreleasepool

    {

       NSString *s = [NSString stringWithFormat:…];

    }// the string object is deallocated here

    但是如果你像下面这样编写代码,则即使 NSString 对象在@autoreleasepool 块中创建,stringWithFormat:方法也确实返回了一个 autorelease 对象,但变 量 s 是 strong 类型的,只要 s 没有退出作用域,string 对象就会一直存在:

    NSString *s;

    @autoreleasepool

    {

       s = [NSString stringWithFormat:…];

    }// the string object is still alive here

    使用 __autoreleasing 可以使 autorelease pool 释放掉该对象,它告诉编 译器这个变量指向的对象可以被 autorelease,此时变量不是 strong 指针, string 对象会在@autoreleasepool 块的末尾被释放。不过注意变量在对象释放后,仍然会继续指向一个死掉的对象。如果你继续使用它,应用就会崩溃。代码如下:

    _autoreleasing NSString *s;

    @autoreleasepool

    {

       s = [NSString stringWithFormat:…];

    }// the string object is deallocated here

    NSLog(@”%@”,s);//crash!

    注意 :Core Foundation 对象不能 autorelease , autorelease 完全纯属于 Objective-C。

  • 相关阅读:
    Excel 小技能
    Socket,ServerSocket,WebSocket
    浅谈Java中的关键字
    线程 学习教程(一): Java中终止(销毁)线程的方法
    OpenGL — GLFW — 颜色
    解决PCL MLS : error LNK2019; error LNK2001 virtual MovingLeastSquares process performProcessing问题
    获取显示屏的个数和分辨率
    Window 显示鼠标的坐标
    OpenCV 鼠标手动绘制掩码图像
    Windows 8 64位系统 在VS2010 32位软件上 搭建 PCL点云库 开发环境
  • 原文地址:https://www.cnblogs.com/417460188dy/p/3220897.html
Copyright © 2011-2022 走看看