内存管理
什么是堆?什么是栈?
答:栈(操作系统):由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈(先进后出); 堆(操作系统):一般由程序员分配释放,若程序员不释放,程序结束时可能由系统回收,分配方式类似于链表。
什么是内存管理?
答:所谓内存管理, 就是对内存进行管理, 涉及的操作有:
分配内存 : 比如创建一个对象, 会增加内存占用
清除内存 : 比如销毁一个对象, 能减小内存占用
内存管理的本质是什么?
答:OC对象存放于堆里面 ;非OC对象一般放在栈里面(栈内存会被系统自动回收)
MRC内存管理
什么是引用计数器?
答:每个OC对象都有自己的引用计数器,它是一个整数,表示有多少人正在用这个对象
引用计数器的作用?
答:(1)当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1;
(2)当对象的引用计数器为0时,对象占用的内存就会被系统回收;
如果对象的计数器不为0,那么在整个程序运行过程,它占用的内存就不可能被回收(除非整个程序已经退出 )
怎么操作引用计数器?
答:给对象发送一条retain消息,可以使引用计数器值+1(retain方法返回对象本身);
给对象发送一条release消息, 可以使引用计数器值-1;
给对象发送retainCount消息, 可以获得当前的引用计数器值。
需要注意的是: release并不代表销毁\回收对象, 仅仅是计数器-1。
dealloc 方法的作用?
答:对象即将被销毁时系统会自动给对象发送一条dealloc消息 (因此, 从dealloc方法有没有被调用,就可以判断出对象是否被销毁)
重写dealloc方法有什么注意点?
答:重写dealloc方法, [super dealloc]一定要写到所有代码的最后
内存管理的原则?
答:(1)谁创建谁release :如果你通过alloc、new、copy或mutableCopy来创建一个对象,那么你必须调用release或autorelease;(2)谁retain谁release:只要你调用了retain,就必须调用一次release;(3)循环引用,一边用retain一边用assign。
autorelease 自动释放池
1.什么是自动释放池?
答: autorelease是一种支持引用计数的内存管理方式,只要给对象发送一条autorelease消息,会将对象放到一个自动释放池中,当自动释放池被销毁时,会对池子里面的所有对象做一次release操作
2.自动释放池的优点是什么?
答: 不用再关心对象释放的时间,不用再关心什么时候调用release
3.简述自动释放池的原理?
答: autorelease实际上只是把对release的调用延迟了,对于每一个autorelease,系统只是把该 Object放入了当前的autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。
4.自动释放池有哪些注意事项?
答: (1)在自动释放池中创建了对象, 一定要调用autorelease,才会将对象放入自动释放池中
(2)一个程序中可以创建N个自动释放池, 并且自动释放池还可以嵌套
(3)不要再自动释放池中使用比较消耗内存的对象, 占用内存比较大的对象
(4)尽量不要再自动释放池中使用循环, 特别是循环的次数非常多, 并且还非常占用内存
(5)千万不要写多次autorelease
(6)一个alloc/new对应一个autorelease或者release
5.自动释放池是以什么形式存储的?
答: 如果存在多个自动释放池的时候, 自动释放池是以 “栈” 的形式存储在堆区
栈的特点: 先进后出
ARC内存管理
1:ARC的原理是什么?
答:当ARC开启时,编译器将自动在代码合适的地方插入retain, release和autorelease,而作为程序猿,完全不需要担心编译器会做错(除非开发者自己错用ARC了)。
ARC有什么优点?
答: 1.完全消除了手动管理内存的烦琐, 让程序猿更加专注于app的业务
2.基本上能够避免内存泄露
3.有时还能更加快速,因为编译器还可以执行某些优化
ARC的原则是什么?什么是强指针?什么是弱指针?
答:只要还有一个强指针变量指向对象,对象就会保持在内存中
(1)强指针 :默认所有指针变量都是强指针 ,被__strong修饰的指针
(2)弱指针 :被__weak修饰的指针
ARC下@property修饰符有哪些?
答: strong : 用于OC对象, 相当于MRC中的retain
weak : 用于OC对象, 相当于MRC中的assign
assign : 用于基本数据类型, 跟MRC中的assign一样
ARC中是怎么对对象进行内存管理的?
答: (1)ARC下单对象内存管理
(2)ARC下,所有的指针都是强指针
(3)ARC, A对象想拥有B对象, 那么就需要用一个强指针指向B对象
(4)A对象不用B对象了, 什么都不需要做, 编译器会自动帮我们做
ARC怎么解决循环引用问题?
答: ARC和MRC一样, 如果A拥有B, B也拥有A, 那么必须一方使用弱指针
也就是说 一端用strong ,一端用weak
类别 Category
1.类别的作用
答:有时我们需要在一个已经定义好的类中增加一些方法,而不想去重写该类。可以使用类别对该类扩充新的方法。
注意:类别只能扩充方法,而不能扩充成员变量。
2.Category的作用?
答:(1)在不改变原来的类内容的基础上,为类增加一些方法。
(2)一个庞大的类可以分模块开发,由多个人来编写,更有利于团队合作
3.分类,原来类或者父类中的方法调用的顺序?
答:先调用分类中的方法(最后参与编译的分类优先),再调用原来类中的方法,最后掉用父类中的方法
匿名扩展Extension
1.什么是类扩展?
答:延展类别又称为扩展(Extension),Extension是Category的一个特例
2.类扩展格式?
答:类扩展书写格式
@interface 类名 ()
@end
3.类扩展的作用是什么?
答:写在.m文件中,可以为某个类扩充一些私有的成员变量和方法
Block
什么是Block?
答:Block是iOS中一种比较特殊的数据类型,用来保存某一段代码
Block的作用?
答:Block用来保存某一段代码, 可以在恰当的时间再取出来调用
功能类似于函数和方法
Block的格式?
答:Block的格式:
返回值类型 (^block变量名)(形参列表) = ^(形参列表) {
};
Block对变量的用法
在block块内部:1.局部变量相当于一个常量,其值不可更改;2.静态局部变量的值可以修改:3.全局变量的值也可以更改。
如果在代码块内部需要对局部变量进行赋值操作,可以在局部变量定义时使用__block来修饰
__block int b1=1000;
void (^MYblock1)(void)=^{
b1++;
NSLog(@"b1=%d",b1);
int b2=11+b1;
NSLog(@"b2=%d",b2);
};
MYblock1();//1001,1012
b1++;
MYblock1();//1003 1014
协议
1.什么是协议?
答:其他语言有接口的概念,接口就是一堆方法的声明没有实现.
OC中没有接口的概念,OC中的接口就是协议.
协议Protocol是由一系列的方法声明组成的
2.书写协议的格式?
答:格式:
@protocol 协议名称
// 方法声明列表
@end
3.一个类怎么遵循协议?
答:格式:
@interface 类名 : 父类 <协议名称1, 协议名称2,…>
@end
注意:
(1)一个类可以遵守1个或多个协议
(2)任何类只要遵守了Protocol,就相当于拥有了Protocol的所有方法声明
4.协议和继承有什么区别?
答: (1)继承之后默认就有实现, 而protocol只有声明没有实现
(2)相同类型的类可以使用继承, 但是不同类型的类只能使用protocol
(3)protocol可以用于存储方法的声明, 可以将多个类中共同的方法抽取出来, 以后让这些类遵守协议即可
5.什么是基协议?
答:基协议:是基协议,是最根本最基本的协议,其中声明了很多最基本的方法。
注意:建议每个新的协议都要遵守NSObject协议
6.协议有哪些注意事项?
答: (1)协议只能声明方法, 不能声明属性
(2)父类遵守了某个协议, 那么子类也会自动遵守这个协议
(3)在OC中一个类可以遵守1个或多个协议
注意: OC中的类只能有一个父类, 也就是说OC只有单继承
(4)OC中的协议又可以遵守其它协议, 只要一个协议遵守了其它协议, 那么这个协议中就会自动包含其它协议的声明
7.协议中控制方法的能否实现的关键字是什么?各有什么作用?
(1)注意: 如果没有使用任何关键字修饰协议中的方法, 那么该方法默认就是required的
(2)注意:@required和@optional仅仅使用程序员之间交流, 并不能严格的控制某一个遵守该协议的类必须要实现该方法, 因为即便不是实现也不会报错, 只会报一个警告
(3) @required :如果协议中的方法是@required的, 要求遵守协议的类实现@required所修饰的方法,如果没有实现该方法, 那么会报一个警告
(4) @optional :如果协议中的方法是@optional的, 遵守协议的类可选择实现@optional所修饰的方法,如果没有实现该方法, 那么不会报警告
代理
1.代理模式的应用场景?
答:(1)当A对象想监听B对象的一些变化时, 可以使用代理设计模式
(2)当B对象发生一些事情, 想通知A对象的时候, 可以使用代理设计模式
(3)当对象A无法处理某些行为的时候,想让对象B帮忙处理(让对象B成为对象A的代理对象)
2.用什么类型来接收遵守协议的代理对象?
答:使用id类型接收代理对象
3.简述一下协议的编写规范?
答:(1)一般情况下, 当前协议属于谁, 我们就将协议定义到谁的头文件中
(2)协议的名称一般以它属于的那个类的类名开头, 后面跟上protocol或者delegate
(3)协议中的方法名称一般以协议的名称protocol之前的作为开头
(4)一般情况下协议中的方法会将触发该协议的对象传递出去
4.一般情况下一个类中的代理属于的名称叫做 delegate
5.当某一个类要成为另外一个类的代理的时候,一般情况下在.h中用@protocol 协议名称;告诉当前类 这是一个协议。在.m中用#import真正的导入一个协议的声明
6.委托代理(degegate),目的是改变和传递控制链
Copy
1.使用copy功能的前提是什么?
答: 使用copy前提:需要遵守NSCopying协议,实现copyWithZone:方法
使用mutableCopy的前提:需要遵守NSMutableCopying协议,实现mutableCopyWithZone:方法
2.如何使用copy功能?
答: 一个对象可以调用copy或mutableCopy方法来创建一个副本对象
copy : 创建的是不可变副本(如NSString、NSArray、NSDictionary)
mutableCopy :创建的是可变副本(如NSMutableString、NSMutableArray、NSMutableDictionary)
3.copy基本原则?
答: 修改源对象的属性和行为,不会影响副本对象
修改副本对象的属性和行为,不会影响源对象
4.为什么通过不可变对象调用了copy方法, 不会生成一个新的对象?
答: 因为原来的对象是不能修改的, 拷贝出来的对象也是不能修改的
既然两个都不能修改, 所以永远不能影响到另外一个对象, 那么已经符合需求
所以: OC为了对内存进行优化, 就不会生成一个新的对象
5.自定义类如何实现copy操作?
答:(1)以后想让自定义的对象能够被copy只需要遵守NSCopying协议
(2)实现协议中的- (id)copyWithZone:(NSZone *)zone
(3)在- (id)copyWithZone:(NSZone *)zone方法中创建一个副本对象, 然后将当前对象的值赋值给副本对象即可
copy内存管理
1.浅复制(浅拷贝,指针拷贝,shallow copy)
源对象和副本对象是同一个对象
源对象(副本对象)引用计数器+1,相当于做一次retain操作
本质是:没有产生新的对象
2.深复制(深拷贝,内容拷贝,deep copy)
源对象和副本对象是不同的两个对象
源对象引用计数器不变,副本对象计数器为1(因为是新产生的)
本质是:产生了新的对象
单例
1.什么是单例模式?
答:类的对象成为系统中唯一的实例,提供一个访问点,供客户类 共享资源
单例就是无论怎么创建都只能有一个实例对象
2.什么情况下使用单例?
答:(1)类只能有一个实例,而且必须从一个为人熟知的访问点对其进行访问,比如工厂方法。
(2)这个唯一的实例只能通过子类化进行扩展,而且扩展的对象不会破坏客户端代码。
3.创建单例对象的方法一般以什么开头?
答:(1)一般情况下创建一个单利对象都有一个与之对应的类方法
(2)一般情况下用于创建单利对象的方法名称都以share开头, 或者以default开头