首页 > 其他 > 详细

Objective-C加强

时间:2017-02-06 13:28:02      阅读:254      评论:0      收藏:0      [点我收藏+]

1.内存管理

内存

  移动设备的内存极其有限,每个app所能占用的内存是有限制的,下列行为都会增加一个app的内存占用
  创建一个OC对象
  定义一个变量
  调用一个函数或者方法

  当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存空间。比如回收一些不需要使用的对象、变量等
  如果app占用内存过大
  系统可能会强制关闭app, 造成闪退现象, 影响用户体验

 

  如何回收那些不需要再使用的对象?那就得学会OC的内存管理

  所谓内存管理, 就是对内存进行管理, 涉及的操作有:
    分配内存 : 比如创建一个对象, 会增加内存占用
    清除内存 : 比如销毁一个对象, 能减小内存占用

  内存管理的管理范围
    任何继承了NSObject的对象
    对其他非对象类型无效(int、char、float、double、struct、enum等 )

  只有OC对象才需要进行内存管理的本质原因
    OC对象存放于里面
    非OC对象一般放在里面(栈内存会被系统自动回收)

堆和栈
  技术分享

什么是引用计数器
  系统是如何判断 什么时候需要回收一个对象所占用的内存?根据对象的引用计数器

  什么是引用计数器
  每个OC对象都有自己的引用计数器,它是一个整数,从字面上, 可以理解为”对象被引用的次数”,也可以理解为: 它表示有多少人正在用这个对象
  技术分享

  每个OC对象内部都有4个字节的存储空间来存放引用计数器


引用计数器的作用
  简单来说, 可以理解为: 引用计数器表示有多少人正在使用这个对象

  当没有任何人使用这个对象时, 系统才会回收这个对象, 也就是说
  当对象的引用计数器为0时,  对象占用的内存就会被系统回收
  如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序已经退出 )

  任何一个对象, 刚生下来的时候, 引用计数器都为1
  当使用alloc、new或者copy创建一个对象时,对象的引用计数器 + 1

引用计数器的操作
  要想管理对象占用的内存, 就得学会操作对象的引用计数器

  引用计数器的常见操作
   给对象发送一条retain消息, 可以使引用计数器值+1(retain方法返回对象本身
   给对象发送一条release消息, 可以使引用计数器值-1
   给对象发送retainCount消息, 可以获得当前的引用计数器值

  需要注意的是: release并不代表销毁\回收对象, 仅仅是计数器-1

dealloc
  当一个对象的引用计数器值为0时
  这个对象即将被销毁,其占用的内存被系统回收,系统会自给对象送一条dealloc消息
  (因此, 从dealloc方法有没有被调用, 就可以判断出对象是否被销毁)

  dealloc方法的重写
  一般会重写dealloc方法, 在这里释放相关资源, dealloc就是对象的遗言
  一旦重写了dealloc方法, 就必须调用[super dealloc],并且放在最后面调用

  使用注意
  不能直接调用dealloc方法
  一旦对象被回收了, 它占用的内存就不再可用, 坚持使用会导致程序崩溃野指针错误

野指针\空指针
  僵尸对象
    已经被销毁的对象(不能再使用的对象)

  野指针
    指向僵尸对象(不可用内存)的指针,给野指针发消息会报EXC_BAD_ACCESS错误

  空指针
    没有指向存储空间的指针(里面存的是nil, 也就是0),给空指针发消息是没有任何反应的

  为了避免野指针错误的常见办法,在对象被销毁之后, 将指向对象的指针变为空指针

关闭ARC功能
  要想手动调用retain、release等方法 , 就必须关闭ARC功能
  技术分享

开启僵尸对象监控
  默认情况下,Xcode是不会管僵尸对象的,使用一块被释放的内存也不会报错。为了方便调试,应该开启僵尸对象监控
  技术分享

多对象内存管理
  单个对象的内存管理, 看起来非常简单

  如果对多个对象进行内存管理, 并且对象之间是有联系的, 那么管理就会变得比较复杂

  其实, 多个对象的管理思路 跟 很多游戏的房间管理差不多,比如斗地主 \ QQ堂

  总的来说, 有这么几点管理规律
    只要还有人在用某个对象,那么这个对象就不会被回收
    只要你想用这个对象,就让对象的计数器+1
    当你不再使用这个对象时,就让对象的计数器-1

内存管理原则
  苹果官方规定的内存管理原则
  谁创建谁release : 如果你通过allocnew[mutable]copy来创建一个对象,那么你必须调用releaseautorelease

  谁retain谁release :只要你调用了retain,就必须调用一次release

  总结一下就是
    有加就有减
    曾经让对象的计数器+1,就必须在最后让对象计数器-1

set方法的内存管理
  set方法

- (void)setCar:(Car *)car
{
    if (car != _car)
    {
        // 对当前正在使用的车(旧车)做一次release
        [_car release];
        
        // 对新车做一次retain操作
              _car = [car retain];
    }
}

dealloc方法的内存管理
dealloc方法

- (void)dealloc
{
    // 当人不在了,代表不用车了
        // 对车做一次release操作
    [_car release];
    [super dealloc];
}

 错误写法
下面代码都会引发内存泄露
  p.dog = [[Dog alloc] init];
  [[Dog alloc] init].weight = 20.8;

@property参数
  控制set方法的内存管理
    retain : release旧值,retain新值(用于OC对象)
    assign : 直接赋值,不做任何内存管理(默认,用于非OC对象类型)
    copy   : release旧值,copy新值(一般用于NSString *)

  控制需不需生成set方法
    readwrite :同时生成set方法和get方法(默认)
    readonly  :只会生成get方法

  多线程管理
    atomic    :性能低(默认)
    nonatomic :性能高

  控制set方法和get方法的名称(起别名)
    setter 设置set方法的名称,一定有个冒号:
    getter 设置get方法的名称

@class
  作用:可以简单地引用一个类

  简单使用
    @class Dog;
    仅仅是告诉编译器: Dog是一个类; 并不会包含Dog这个类的所有内容
  
  具体使用
    在.h文件中使用@class引用一个类
    在.m文件中使用#import包含这个类的.h文件


@class和#import
  作用上的区别
    #import会包含引用类的所有信息(内容), 包括引用类的变量和方法
    @class仅仅是告诉编译器有这么一个类, 具体这个类里有什么信息, 完全不知

  效率上的区别
    如果有上百个头文件都#import了同一个文件,或者这些文件依次被#import,那么一旦最开始的头文件稍有改动,

    后面引用到这个文件的所有类都需要重新编译一遍 , 编译效率非常低,相对来讲,使用@class方式就不会出现这种问题了

@class
  其他使用场景
  对于循环依赖关系来说,比方A类引用B类,同时B类也引用A类
  技术分享

  这种嵌套包含的代码编译会报错
  当使用@class在两个类相互声明,就不会出现编译报错
  技术分享

循环retian
  循环retain的场景
  比如A对象retain了B对象,B对象retain了A对象

  循环retain的弊端
  这样会导致A对象和B对象永远无法释放

  循环retain的解决方案
  当两端互相引用时,应该一端用retain、一端用assign

autorelease简介
  autorelease方法的基本作用
    给对象发送一条autorelease消息, 会将对象放到一个自动释放池中
    当自动释放池被销毁时,会对池子里面的所有对象做一次release操作
    会返回对象本身
    调用完autorelease方法后,对象的计数器不变

  autorelease的好处
    不用再关心对象释放的时间
    不用再关心什么时候调用release

  autorelease的使用注意
    占用内存较大的对象不要随便使用autorelease
    占用内存较小的对象使用autorelease,没有太大影响

自动释放池
  在iOS程序运行过程中,会创建无数个池子。这些池子都是以结构存在(先进后出)

  当一个对象调用autorelease方法时,会将这个对象放到栈顶的释放池

  自动释放池的创建方式
     iOS 5.0前
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; [pool release]; // [pool drain];

    iOS 5.0 开始
    @autoreleasepool {  
     }
  
autorelease的常见错误
  alloc之后调用了autorelease,又调用release
  Person *p = [[[Person alloc] init] autorelease];
  [p release];

  连续调用多次autorelease
  Person *p = [[[[Person alloc] init] autorelease] autorelease];

autorelease和release使用对比
  使用release
    Book *book = [[Book alloc] init];
    [book release];

  使用autorelease
    Book *book = [[[Book alloc] init] autorelease];
    // 不要再调用[book release];

autorelease的应用场合
  一般可以为类添加一个快速创建对象的类方法
    + (id)book {
       return [[[self alloc] init] autorelease];
    }
  外界调用[Book book]就可以获得和使用新建的Book对象,根本不用考虑在什么时候释放Book对象

  一般来说,除了alloc、newcopy之外的方法创建的对象都被声明了autorelease

  比如下面的对象都已经是autorelease的,不需要再release
    NSNumber *n = [NSNumber numberWithInt:100];
    NSString *s = [NSString stringWithFormat:@"jack"];
    NSString *s2 = @"rose";


2.ARC(自动引用计数)
ARC简介
  ARC是自iOS 5之后增加的新特性, 是iOS程序猿的福音

  ARC的全称是Automatic Reference Counting(自动引用计数)

  ARC的实现细节
    编译器会自动在适当的地方插入适当的retain、release、autorelease语句
    也就是说, 编译器会自动生成内存管理的代码, 不用程序猿手动编写

    如果是手动管理内存, 可以简称MRC (Manual Reference Counting)

ARC的注意点和优点
  ARC的注意点
    ARC是编译器特性,而不是运行时特性
    ARC不是其它语言中的垃圾回收, 有着本质区别

  ARC的优点
    完全消除了手动管理内存的烦琐, 让程序猿更加专注于app的业务
    基本上能够避免内存泄露
    有时还能更加快速,因为编译器还可以执行某些优化


ARC的判断原则
  ARC的判断原则
    只要还有一个强指针变量指向对象,对象就会保持在内存中

  强指针
    默认所有指针变量都是强指针
    被__strong修饰的指针

    弱指针
    被__weak修饰的指针

ARC的使用细节
  不能调用release、retain、autorelease、retainCount

  可以重写dealloc,但是不能调用[super dealloc]

  ARC中的@property
      strong : 用于OC对象, 相当于MRC中的retain
      weak : 用于OC对象, 相当于MRC中的assign
      assign : 用于基本数据类型, 跟MRC中的assign一样
      copy : 一般用于NSString, 跟MRC中的copy一样


MRC转为ARC
  技术分享

 

3.Category
什么是Category
  Category有很多种翻译: 分类 \ 类别 \ 类目 (一般叫分类)

  Category是OC特有的语法, 其他语言没有的语法

  Category的作用
  可以在不修改原来类的基础上, 为这个类扩充一些方法

书写格式
  声明
  @interface 类名 (分类名称)
  @end

  实现
  @implementation类名 (分类名称)
  @end


























 



























Objective-C加强

原文:http://www.cnblogs.com/laugh/p/6369841.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!