内存管理和 Block

ARC:

指定文件编译时用 ARC 机制,指定编译属性:-fobjc-arc,非 ARC :_fno-objc-arc

1.黄金法则:

对象调用一次:alloc new copy mutablecopy(自己生成并持有的) retain(非自己生成,而持有的)
就必须调用一次:release autorelease(对自己持有的对象可以进行 release autorelease)

2.工厂方法
Foundation 提供的工厂方式的实现:

+ (id) object
{
    // 自己生成并持有
    id obj = [[NSObject alloc] init];

    // 放到自动释放池中管理,该方法可以取得对象的存在,但是自己不持有
    [obj autorelease];

    return obj;
}

一般情况下自己实现的工厂方法

+ (id) object
{
    // 自己生成并持有
    id obj = [[NSObject alloc] init];
    // 没有放到自动释放池中管理该对象

    return obj;
}

所以:Foundation提供的工厂方法获得对象不能调用 release autorelease,因为里面已经存在了autorelease
一般自己实现的工厂方法是可以调用 release autorelease 方法的

3.autorelease的内部实现 (GNUstep)

- (id)autorelease
{
    [NSAutoreleasePool addObject:self];
}

autorelease实例方法的本质就是调用 NSAutoreleasePool对象的 addObject:方法,把对象添加到自动释放池中

4.所有的权限修饰符:__strong __weak __unsafe_unretained __autoreleasing

1> __strong

__strong 强应用,默认变量的类型
__strong修饰的变量 obj 在超出其变量的作用域时,会释放其被赋予的对象。
注意:强引用之间的赋值对内存的影响。

2> __weak

__weak 弱引用
__weak 只有用在 ARC 机制下,作用才能显示出来。
在持有某对象的弱引用时,该对象被废弃,此弱引用将自动失效且处于nil 被赋值的状态。
还有一个作用就是防止循环强引用。

3> __unsafe_unretained

__unsafe_unretained在低版本中替代__weak的
作用:__unsafe_unretained 和 __weak 一样,自己生成的对象自己不能持有,也就是在生成销毁

4> __autoreleasing

在 ARC 有效时,不能使用 NSAutoreleasePool 和 autorelease
用@autoreleasepool 替代 NSAutoreleasePool
用__autoreleasing 替代 autorelease

将对象赋值给用__autoreleasing 修饰的变量等价于对象调用了 autorelease方法

__strong __weak __autoreleasing 可以将修饰的变量初始化为 nil

5.属性
属性声明与所有权修饰符之前的对应关系

assign:__unsafe_unretained
copy:__strong
retain:__strong
strong:__strong
unsafe_unretianed:__unsafe_unretained
weak:__weak

Block

block是 C 语言的扩充:带有自动变量的匿名函数

1.block语法与一般的 C 语言函数相比的差别:

1> 没有函数名
2> 带有^

第一点不同因为他是匿名函数,第二点不同是返回值前带有^

2.语法格式:
1> ^ 返回值类型 参数列表 表达式

^int (int count){
    return count+1;
}

Block 的省略
2> ^ 参数列表 表达式
返回值类型可以根据return 的类型来推断

^(int count){
    return count + 1;
}

3> ^ 表达式
返回值类型和参数列表都被省略

^{
    printf("Blocks\b");
}

3.block类型的变量
返回类型 (^变量名)(参数)

// 声明了一个 blk变量
int (^blk)(int);

Block 类型的变量和C 语言的函数指针的差别
就是变量前的* 换成了 ^

4.自动变量
在 block 中获取外部变量的值存储在 block 自带的自动变量中,以后再改变外部变量的值,block 内部的自动变量值不会改变。

int main(){
    int val = 0;
    // 定义一个 block 变量并赋值
    void(^blk)(void) = ^{
        //  val 是 block 自带的自动变量值
        printf("val = %d\n",val);
    };
    // 调用 block 方法 输出 val = 0;
    blk();
    // 改变外部变量的值
    val = 1;
    // 再次调用 block 方法 输出 val = 0
    blk();
}

不能在 block 内部改变外部变量的值
__block修饰的变量可以在 block 中赋值,该变量称为__block变量
Block 是存在栈上的实例变量

栈的 block 复制到堆上调用的函数 copy
堆上 block 被废弃是调用函数 dispose 函数

什么时候栈上 block 会复制到堆上

1> 调用 block 的 copy 实例方法
2> block 作为函数返回值时
3> 将 block 赋值给有__strong 修饰的id 类型或 block 类型

Block循环引用

对象拥有 block 实例变量,block 中拥有对象的 self。
会引起循环引用,所以要把 block 实例变量前加 __weak
__block 来避免循环引用,定义一个__block类型的变量,然后将 self 赋值给他。

__block变量持有对象还持有Block ,对象持有 block

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值