您的位置:首页 > 职场人生

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

2015-09-18 23:19 519 查看
------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变量用作方法的参数的时候,最好把参数类型列表部分加上 具体的形参名
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: