黑马程序员——ios开发基础之OC内存管理与blocks

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

第一讲    内存管理

1. 内存管理概念理解
          1)内存管理的范围
                  所有的OC对象(继承自NSObject类)
          2)为什么内存管理只管理OC对象?
                  堆中内存不连续, 无法自动释放
          3)如何对OC对象进行内存管理?
                  通过操作对象的"引用计数器"
2. 引用计数器
       引用计数器概念 
          1)每个OC对象都有自己的引用计数器
          2)它是一个整数(int类型, 占用4个字节)
          3)从字面上, 可以理解为"对象被引用的次数"
          4)也可以理解为: 它表示有多少人正在用这个对象
     引用计数器的作用
         1) 系统通过"引用计数器"来判断当前对象是否可以被释放
    对象的"引用计数器"的操作方式
           1)retain, +1
           2)release, -1
           3)retainCount, 获取对象引用计数器的值
3. dealloc方法
          1)当对象即将被销毁, 系统自动给对象发送一条dealloc消息
          2)因此, 从dealloc方法有没有被调用, 就可以判断出对象是否被销毁
          3)重写了dealloc方法, 必须调用[super dealloc], 并且放在最后面调用
          4)不要自己直接调用dealloc方法
          重写dealloc方法,代码规范
           (1) 一定要[super dealloc],而且要放到最后,意义是:先释放子类占用的空间在释放父
                      类占用的空间
           (2)对self(当前)所拥有的的其他对象做一次release操作
                   -( void) dealloc{
                      [_car release];
                      [super dealloc];
                     }
4. 多对象内存管理
         -(void)setCar:(Car*)car{
                _car = car;
          }
          对象已经释放了,再次去使用
              [car release];
               [p driver]; // _car = [car retain];
          给p.car 设置不同对象的时候会造成原对象内存泄露
              p.car = car1;
             [car1 release]; //car1 1
             p.car = car2; // [_car release];  _car = [car retain];
              //
             p.car = car1; //car1 2
             [car1 release]; // 1
             p.car = car1; // if(_car != car){_car release]; _car = [car retain];}
5. @property的修饰关键字
      1)控制set方法的内存管理
             retain: release旧值, retain新值(用于OC对象),要配合nonatomic使用
             assign: 直接赋值, 不做任何内存管理(默认, 用于非OC对象类型)
             copy: release旧值, copy新值(一般用于NSString *)
      2)控制是否需要生成set方法
             readwrite: 同时生成set方法和get方法(默认)
             readonly: 只会生成get方法
     3)多线程管理
            atomic: 性能低(默认)
            nonatomic: 性能高(为iOS系统开发软件建议使用,为mac开发软件可以使用atomic)
     4)控制set方法和get方法的名称
               setter: 设置set方法的名称, 一定有个冒号:
               getter: 设置get方法的名称
6. @class用法
            @class
       .h  @class Dog
       .m    #import "Dog.h"
     @class和#import的区别
      通过@class解决循环依赖问题
7. 内存管理时的循环retain问题
       解决办法: 一端用retain、一端用assign
       注意: 使用了assign后, dealloc中就不需要release了
8. 对象自动释放池的使用
       对于autorelease pool本身,会在如下两个条件发生时候被释放
      1)手动释放Autorelease pool
      2) Runloop结束后自动释放
          对于autorelease pool内部的对象
         在引用计数的retain == 0的时候释放。 release和autorelease pool 的 drain都会触发retain--事件。
      1、autorelease使用注意
             1)并不是放到自动释放池代码中,都会自动加入到自动释放池,不管这个对象是在自动释放池内还是外创建的,只要在自动释放池内写一个                      [p1  autorelease];p1就会被放到自动释放池中。注意autorelease是一个方法,且只有在自动释放池中使用才有效。
       2、autorelease错误用法
       ( 1)连续调用多次autorelease,释放池销毁时执行两次release(-1)吗
       ( 2) Alloc之后调用了autorelease,之后又调用了release。
9、应用:创建一个学生类,初始化年龄
      
student.h
#import <Foundation/Foundation.h>
@interface Student : NSObject
@property(nonatomic,assign) int age;
-(instancetype)initWithAge:(int)age;
+(instancetype)studentWithAge:(int)age;
@end
student.m
#import "Student.h"
@implementation Student
- (void)dealloc
{
   NSLog(@"Student 被释放");
    [super dealloc];
}
//自定义构造方法
-(instancetype)initWithAge:(int)age{
   if (self = [super init]) {
       _age = age;
}
return self;
}
//自定义初始化方法
+(instancetype)studentWithAge:(int)age{
   return [[[self alloc] initWithAge:age] autorelease];
}
@end
main.m
#import <Foundation/Foundation.h>
#import "Student.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
      // Student *stu = [[[Student alloc] initWithAge:10] autorelease];
       Student *stu1 = [Student studentWithAge:100];
        NSLog(@"age = %d",stu1.age);
}
return 0;
}

10、ARC

          自动引用计数,即ARC,当ARC开启时,编译器将自动在代码合适的地方插入retain, release和autorelease

         判断准则: 

         只要没有强指针指向对象,对象就会被释放。

         1)强指针
              所有的指针默认就是强指针
              强指针使用 strong 标识

           2)弱指针
              所有的指针默认就是强指针
              弱指针使用__week 标识

            循环引入的对象中其中一个对象设置为 strong 另一个设置为 weak

         ARC中的@property
               strong : 用于OC对象, 相当于MRC中的retain
               weak : 用于OC对象, 相当于MRC中的assign
              assign : 用于基本数据类型, 跟MRC中的assign一样
               copy : 一般用于NSString, 跟MRC中的copy一样
               在ARC情况下解决”循环retain” 的问题: @property一边用strong,一边用weak。

第二讲  blocks

1、block概念
        可执行代码,Block对象包含着一组状态数据,
         这些数据在程序执行时用于对行为产生影响。
2、使用方法
       1) block最简单形式
          定义格式:
            void (^block名)() = ^{代码块;}
    使用格式:block名();
       2) block带有参数的block的定义和使用
           格式:
          void (^block名称)(参数列表)= ^ (参数列表) { // 代码实现; }
       3) 带有参数和返回值的block
            格式:
        返回类型 (^block名称)(参数列表)= ^ 返回类型 (参数列表) { // 代码实现; }
3、block的typedef
      利用typedef定义block类型(和指向函数的指针很像)
       格式:
          Typedef int(^MyBlock)(int ,int);
            速记符
          typedef 返回值类型 (^block变量名)(参数类型列表);
4、 block访问外部变量
           1)在block内部可以访问block外部的变量
               2)在block内部不可以修改block外部的变量
               3)给局部变量加上__block关键字,则这个局部变量可以在block内部进行修改。
5、block使用技巧及注意
            1) block 结构的快速提示:inlineBlock 
           2) block变量用作方法的参数的时候,最好把参数类型列表部分加上 具体的形参名

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值