码迷,mamicode.com
首页 > 其他好文 > 详细

Foundation => Objective-C _ Part4

时间:2016-04-29 16:23:36      阅读:112      评论:0      收藏:0      [点我收藏+]

标签:

1. 内存管理

  1. 堆和栈
    • 栈 (操作系统) : 由操作系统自动分配释放, 存放函数的参数值(形参),局部变量的值等. 其操作方式类似于数据结构中的栈 (先进后出)
    • 堆 (操作系统) : 一般由程序员分配释放, 若程序员不释放, 程序结束时可能由OS回收, 分配方式类似于链表
    • 只要是alloc init创造的, 都放在堆里
    • OC对象存放在堆里,堆里的数据系统不会自动释放, 需要手动释放
    • 非OC对象一般放在栈里, 栈内存会被系统自动回收
  2. 内存泄漏 - - - 如果一个OC对象,占据了一块内存, 但又没有被使用. 那么这个现象就是内存泄露
  3. 引用计数器的作用 - - - 引用计数器表示有多少人正在使用这个对象
  4. 引用计数器的操作
    • 对象被创建, 引用计数器初始就是1
    • 给对象发送一条retain消息, 引用计数器就+1
    • 给对象发一条release消息, 引用计数器 - 1
    • 给对象发retainCount, 可以获得当前引用计数器的值 (获得的值并不准确)
  5. dealloc
    • 当一个对象引用计数器为0, 系统会自动给对象发一条dealloc消息.(因此从dealloc方法有没有被调用, 就知道对象是否被销毁)
    • 一般会dealloc方法的重写, 在这里释放相关的资源, dealloc就是对象的遗言
    • 一旦重写了dealloc方法, 就必须调用[super dealloc] 并且放在最后调用
    • 不能直接调用dealloc方法
    • 一旦对象被回收了, 它占用的内存就不可再用, 坚持使用会导致程序崩溃(野指针错误)
  6. 野指针和空指针
    • 野指针
      • 只要一个对象被释放了, 我们就称这个对象为 “僵尸对象”
      • 当一个指针指向一个僵尸对象, 我们就称这个指针为野指针
      • 只要给一个野指针发送消息就会报错
      • [Person release]: message sent to deallocated instance 0x1001146b0
    • 空指针
      • 为了避免给野指针发送消息会报错, 一般情况下, 当一个对象被释放后我们会将这个对象的指针设置为空指针
      • 因为在OC中给空指针发送消息是不会报错的
  7. ARC 和 MRC
    • ARC : Automatic(自动) Reference(引用) Counting(计数)
      • 什么是自动引用计数?
      • 不需要程序员管理内容, 编译器会在适当的地方自动给我们添加release/retain等代码
      • 注意点: OC中的ARC和java中的垃圾回收机制不太一样, java中的垃圾回收是系统干得, 而OC中的ARC是编译器干得
    • MRC: Manul(手动) Reference(引用) Counting(计数)
      • 什么是手动引用计数?
      • 所有对象的内容都需要我们手动管理, 需要程序员自己编写release/retain等代码
  8. 内存管理的原则 - - - 有加就有减
    • 例如: 一次alloc对应一次release, 一次retain对应一次relese
  9. 多对象内存管理
    • 当A对象想使用B对象一定要对B对象进行一次retain, 这样才能保证A对象存在B对象就存在, 也就是说这样才能保证无论在什么时候在A对象中都可以使用B对象
    • 当A对象释放的时候, 一定要对B对象进行一次release, 这样才能保证A对象释放了, B对象也会随之释放, 避免内存泄露
    • 总结一句话: 有增就有减

3. property修饰符

  1. 相同类型的property修饰符不能同时使用
  2. 不同类型的property修饰符可以多个结合在一起使用, 多个之间用,号隔开
  3. iOS开发中只要写上property, 那么就立刻写上nonatomic
  4. 多线程
    • atomic:性能低(默认)
    • nonatiomic:性能高
    • 在iOS开发中99.99%都是写nonatomic
readonly只会生成getter方法
readwrite: 既会生成getter也会生成setter, 默认什么都不写就是readwrite
getter: 可以给生成的getter方法起一个名称
setter: 可以给生成的setter方法起一个名称
retain: 就会自动帮我们生成getter/setter方法内存管理的代码
assign: 不会帮我们生成set方法内存管理的代码, 仅仅只会生成普通的getter/setter方法, 默认什么都不写就是assign

4. @class

  • 提高编译效率
    #import"Car.h"
    - 由于import是一个预编译指令, 他会将""中的文件拷贝到import所在的位置
    - 并且import有一个特点, 只要""中的文件发生了变化, 那么import就会重新拷贝一次(更新操作)

    @class Car;
    @class仅仅是告诉编译器, @class后面的名称是一个类, 不会做任何拷贝操作

    注意 : 由于@class仅仅是告诉编译器后面的名称是一个类, 所以编译器并不知道这个类中有哪些属性和方法, 所以在.m中使用这个类时需要import这个类, 才能使用

    总结 : 
    1. 如果都在.h中import, 假如A拷贝了B, B拷贝了C ,  如果C被修改了, 那么B和A都需要重新拷贝. 因为C修改了那么B就会重新拷贝, 而B重新拷贝之后相当于B也被修改了, 那么A也需要重新拷贝. 也就是说如果都在.h中拷贝, 只要有间接关系都会重新拷贝
    2. 如果在.h中用@class, 在.m中用import, 那么如果一个文件发生了变化, 只有和这个文件有直接关系的那个文件才会重新拷贝
    3. 所以在.h中用@class可以提升编译效率
  • 相互拷贝变为可行
    • 如果两个类相互拷贝, 例如A拷贝B, B拷贝A, 这样会报错
    • 如何解决: 在.h中用@class, 在.m中用import
    • 因为如果.h中都用import, 那么A拷贝B, B又拷贝A, 会形成死循环
    • 如果在.h中用@class, 那么不会做任何拷贝操作, 而在.m中用import只会拷贝对应的文件, 并不会形成死循环

5. 循环retain

  1. 如果A对用要拥有B对象, 而B对应又要拥有A对象, 此时会形成循环retain
  2. 如何解决这个问题: 不要让A retain B, B retain A
  3. 让其中一方不要做retain操作即可

6. autoRelease的注意事项

  1. 一个程序中可以创建多个自动释放池, 并且自动释放池还可以嵌套
  2. 如果存在多个自动释放池时, 自动释放池是以”栈”的形式存储的 - - - 栈的特点: 先进后出
  3. 千万不要写多个auturelease
  4. 一个alloc / new 对应一个autorelease 或者 release
  5. 如果写了autorelease,就不要写release

7.ARC

  • ARC的判断标准: 只要没有强指针指向对象, 对象就会被释放
  • 默认情况下所有的指针都是强指针
    __strong Person *p = [[Person alloc]init];      //这个是强指针创建的
    __weak  Person *p = [[Person alloc]init];       //这个是弱指针创建的,  会被立即释放
  • 在ARC中如果保存对象, 不要用assign, 要用weak - - - assign是专门用于保存基本数据类型的. 保存对象要用weak
  • ARC和MRC的区别
    • MRC, A对象想要拥有B对象, 需要对B对象进行一个retain
      • A对象不用B对象了, 需要对B对象进行一个release
      • property的时候进行retain, dealloc的时候进行release
    • ARC, A对象想拥有B对象, 需要用一个强指针指向B对象
      • A对象不用B对象了, 什么都不用做. 编译器自动帮们我做
    • 在ARC中保存一个对象用strong, 相当于MRC中的retain

8.分类

  • 基本概念
    • 只能在类别中添加方法, 但不能添加变量
    • 写法
        @interface ClassName (CategoryName)  NewMethod;
        1. ClassName  分类的名称
        2. CategoryName  扩充的方法
        3. NewMethod  扩充的方法
  • 匿名分类 - - - (也叫 “延展” “类扩展”)
    - 作用 - - - 可以为某个类扩充一些私有的成员变量和方法
    - 实际上, 匿名分类, 就是在.m文件里, 写上的@interface 类名() @end
    - 要多多积累自己的分类控件, 便于积累, 以提升开发效率
  • 注意事项
    • 分类是用于给原有类添加方法的, 它只能添加方法, 不能添加属性(成员变量),
    • 分类中的@property, 只会生成setter/getter方法的声明, 不会生成实现以及私有的成员变量
    • 可以在分类中访问原有类中.h的属性
    • 方法调用的
      • 分类
      • 本类
      • 父类
    • 注意
      • 如果分类中有和原有类同名的方法, 会调用分类中的方法 (忽略原有类的方法) ———建议不要这么写
      • 如果多个分类都有和原有类同名的方法, 那么调用该方法的时候执行谁, 由编译器决定( 会执行最后一个参与编译的分类的方法)

9.Block

  1. 定义 - - - Block是iOS中一种比较特殊的数据类型, 和”指向函数”相似
  2. 应用场景 - - - 当发现代码的前面和后面都是一样的时候,这个时候就可以用Block
    • 动画
    • 多线程
    • 集合遍历
    • 网络请求回调
  3. 作用
    • 用来保存某一段代码,可以再恰当的时间再取出来调用
    • 功能类似于函数和方法
  4. 格式
    • 返回值类型(^block变量名)(形参列表) = ^(形参列表){ 代码段 };
    • 例如
void(^roseBlock)();
1. ()代表block将来保存的代码没有形参
2. (^roseBlock)代表roseBlock是一个block变量,可以用于保存一段block代码
3. 如果block没有参数, 那么^后面的()可以省略

例如:
int multiplier = 7;
int (^myBlock)(int) = ^(int num){ return num *multiplier ;};

1. ^符号将myBlock声明为一个块对象
2. myBlock 是块对象, 返回整型值
3. (int)  代表有一个参数,参数的类型也是整型值
4. ^(int num)   参数的名称是num
5. { return num *multiplier ;}  这是块对象的主体部分
6. ^(int num){ return num *multiplier ;}    这是定义块对象的语法结构, 这部分就是赋给myBlock变量的值

10. Block的注意事项

  1. Block和typedef
    • 注意: 利用typedef给block其别名,和指向函数的指针一样, block变量的名称就是别名
    • 推荐用typedef定义别名, 在编码中, 用别名会更加简单
  2. Block的注意事项
    • block中可以访问外面的变量
    • block中可以定义和外界同名的变量, 并且如果在block中定义了和外界同名的变量, 在block中访问的是block中的变量
    • 默认情况下, 不可以在block中修改外界变量的值
      • 因为block中的变量和外界的变量并不是同一个变量
      • 如果block中访问到了外界的变量, block会将外界的变量拷贝一份到堆内存中
      • 因为block中使用的外界变量是copy的, 所以在调用之前修改外界变量的值, 不会影响到block中copy的值
    • 如果想在block中修改外界变量的值, 必须在外界变量前面加上__block
      • 如果在block中修改了外界变量的值, 会影响到外界变量的值
    • block是存储在堆中还是栈中
      • 默认情况下block存储在栈中, 如果对block进行一个copy操作, block会转移到堆中
      • 如果block在栈中, block中访问了外界的对象, 那么不会对对象进行retain操作
      • 但是如果block在堆中, block中访问了外界的对象, 那么会对外界的对象进行一次retain
      • 如果在block中访问了外界的对象, 一定要给对象加上__block, 只要加上了__block, 哪怕block在堆中, 也不会对外界的对象进行retain
      • 如果是在ARC开发中就需要在前面加上__weak

Foundation => Objective-C _ Part4

标签:

原文地址:http://blog.csdn.net/purgeyhy/article/details/51262050

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!