1.ARC 相对于GC的优点和缺点
优点:1.ARC工作在编译期,在运行时没有额外开销。
2.ARC的内存回收是平稳进行的,对象不被使用时会立即被回收。而GC的内存回收是一阵一阵的,回收时需要暂停程序,会有一定的卡顿。
缺点:1.GC太简单了,基本上完全不用处理内存管理的问题,而ARC还是需要处理类似循环引用这种内存管理问题。
2.GC一类的语言相对来说学习起来更简单。
2.instancetype和id的异同
- 相同点
都可以作为方法的返回类型 - 不同点
1.instancetype可以返回和方法所在类相同类型的对象,id只能返回未知类型的对象;
2.instancetype只能作为返回值,不能像id那样作为参数
3.isKindOfClass和isMemberOfClass的区别
isKindOfClass来确定一个对象是否是一个类的成员,或者是派生自该类的成员
isMemberOfClass只能确定一个对象是否是当前类的成员
4.load和initialize的区别
load、initialize.png1.load
和initialize
方法都会在实例化对象之前调用,以main函数为分水岭,前者在main函数之前调用,后者在之后调用。这两个方法会被自动调用,不能手动调用他们。
2.load
和initialize
方法都不用显示的调用父类的方法而是自动调用,即使子类没有initialize
方法也会调用父类的的方法。而load
方法则不会调用父类。
3.load
方法通常用来进行Method Swizzle,initialize
方法一般用于初始化全局变量或静态变量。
4.load
和initialize
方法内部使用了锁,因此他们是线程安全的。实现时要尽可能保持简单,避免阻塞线程,不要再使用锁。
http://www.jianshu.com/p/d25f691f0b07
5.loadVIew是干什么用的?
很多人都会疑惑self.view,这个view到底是哪里来的,就是在这里。一般不需要去操作这个。但如果有特殊的需求,要求这个self.view是我们自己自定义的view时候就可以用这个方法
MyView *myview = [[MyView alloc]init];
self.view = myview;
像上面一样重写一下就行了。
切记: 不要自己调用-loadVIew -viewDidLoad
6.new 与 alloc/init区别
alloc分配内存的时候使用了zone,它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗更少的代价,提升了程序处理速度
为什么不推荐使用new?
如果使用new的话,初始化方法被固定死只能调用init。而你想调用initXXX怎么办?没门儿!
概括来说,new和alloc/init在功能上几乎是一致的,分配内存并完成初始化。
差别在于,采用new的方法只能采用默认的init方法完成初始化,
采用alloc的方式可以用其他定制的初始化方法。
http://blog.csdn.net/lvxiangan/article/details/44906035
7.OC是否可以实现多继承
OC不可以多重继承,可以用代理来代替多继承的功能,可以遵守多个协议,用逗号隔开。
也可以通过组合的方式实现
实例 现在ClassC需要继承ClassA中methodA、ClassB中methodB
@interface ClassC : NSObject {
ClassA *a;
ClassB *b;
}
-(id)initWithA:(ClassA *)A b:(ClassB *)B;
-(void)methodA;
-(void)methodB;
@end
@implementation ClassC
-(id)initWithA:(ClassA *)A b:(ClassB *)B{
a=[[ClassA alloc] initWithClassA: A];//[A copy];
b=[[ClassB alloc] initWithClassB: B];//[B copy];
}
-(void)methodA{
[a methodA];
}
-(void)methodB{
[b methodB];
}
8.深复制浅复制
对于容器对象,发生深拷贝时对容器对象本身来说是深拷贝,因为产生了新对象,而对容器内的元素来说是浅拷贝。即:修改容器内的元素,无论是原来对象还是拷贝产生的新对象,两个容器内的元素都会发生变化,因为容器内存的是容器元素的内存地址。如果想让容器对象本身及容器内的元素都发生深拷贝,使用归档。先归档,再解档。
浅 复 制:在复制操作时,对于被复制的对象的每一层复制都是指针复制。
深 复 制:在复制操作时,对于被复制的对象至少有一层复制是对象复制。
完全复制:在复制操作时,对于被复制的对象的每一层复制都是对象复制。
retain:始终是浅复制。引用计数每次加一。返回对象是否可变与被复制的对象保持一致。
copy:对于可变对象为深复制,引用计数不改变;对于不可变对象是浅复制,
引用计数每次加一。始终返回一个不可变对象。
mutableCopy:始终是深复制,引用计数不改变。始终返回一个可变对象。
不可变对象:值发生改变,其内存首地址随之改变。
可变对象:无论值是否改变,其内存首地址都不随之改变。
引用计数:为了让使用者清楚的知道,该对象有多少个拥有者(即有多少个指针指向同一内存地址)。
简化为:
问:什么时候用到深浅拷贝?
答:深拷贝是在要将一个对象从可变(不可变)转为不可变(可变)或者将一个对象内容克隆一份时用到;
浅拷贝是在要复制一个对象的指针时用到。
巨详细
http://www.cnblogs.com/langtianya/p/3722129.html
9.Copy到底什么时候用?
在OC里面有个值对象的概念,当你新定义一个属性是值对象时就应该用copy来修饰。那么都什么对象是值对象呢?
值对象: 指封装了基本值(属于 C 数据类型)且提供与该值相关的服务的对象。值对象以对象形式表示标量类型。Foundation 框架向您提供了以下类(这些类产生对象,用于字符串、二进制数据、日期与时间、数字以及其他值):
NSString和NSMutableString , NSData和NSMutableData , NSDate , NSNumber , NSValue
http://blog.csdn.net/u010664555/article/details/41786815
http://www.jianshu.com/p/26210296fa02
NSNumber和NSValue的简单使用
http://blog.csdn.net/lushuner/article/details/48494493
NSValue与@encode
http://www.jianshu.com/p/0e6626d3614c
还是参照下面吧
@property内存管理策略的选择
1.非ARC
1> copy : 只用于NSString\block;
2> retain : 除NSString\block以外的OC对象;
3> assign : 基本数据类型、枚举、结构体(非OC对象),当2个对象相互引用,一端用retain,一端用assign。
2.ARC
1> copy : 只用于NSString\block;
2> strong : 除NSString\block以外的OC对象;
3> weak : 当2个对象相互引用,一端用strong,一端用weak;
4> assgin : 基本数据类型、枚举、结构体(非OC对象)。
https://my.oschina.net/aofe/blog/266677
10.weak变量在引用计数为0时,会被自动设置为nil,这个特性是如何实现的?
简单来说,系统有一个全局的CFMutalbeDictionary实例,来保存每个对象的weak指针列表,因为每个对象可能有多个weak指针,所以这个实例的值是CFMutableSet类型。
剩下我们要做的,就是在引用计数变成0的时候,去这个全局的字典里面,找到所有的weak指针,将其值设置为nil。如何做到这一点呢?Friday QA上介绍了一种类似KVO实现的方式。当对象存在weak指针时,我们可以将这个实例指向一个新创建的子类,然后修改这个子类的release方法,在release方法中,去全局的CFMutableDictionary字典中找到所有的weak对象,并且设置为nil。
11.响应者链
事件沿着一个指定的路径传递直到它遇见可以处理它的对象。首先一个UIApplication对象从队列顶部获取一个事件并分发它以便处理。通常,它把事件传递给应用程序的关键窗口对象,该对象把事件传递给一个初始对象来处理。初始对象取决于事件的类型。
如果父控件不能接收触摸事件,那么子控件就不可能接收到触摸事件
事件的完整处理过程:
1.先将事件对象由上往下传递(由父控件传递给子控件),找到最合适的控件来处理这个事件
2.调用最合适控件的touches..方法
3.如果调用了[super touches..]就会将事件顺着响应者链条往上传递,传递给上一个响应者
4.接着就会调用上一个响应者的touches..方法
上一个响应者:
1.如果当前这个view是控制的view,那么控制器就是上一个响应者
2.如果当前这个view不是控制器的view,那么父控件就是上一个响应者
事件传递机制:
1.当iOS程序中发生触摸事件后,系统会将事件加入到UIApplication管理的一个任务队列中
2.UIApplication将处于任务队列最前端的事件向下分发。即UIWindow。
3.UIWindow将事件向下分发,即UIView。
4.UIView首先看自己是否能处理事件,触摸点是否在自己身上。如果能,那么继续寻找子视图。
5.遍历子控件,重复以上两步。
6.如果没有找到,那么自己就是事件处理者。
7.如果自己不能处理,那么不做任何处理。
其中 UIView不接受事件处理的情况主要有以下三种
1)alpha <0.01
2)userInteractionEnabled = NO
3.hidden = YES
回答:
1.响应者链条是由多个响应者对象链接起来的链条(什么是响应者对象:能处理事件的对象)
2.利用响应者链条,能让多个控件处理同一个触摸事件
3.怎么利用链条往上传递?是是上一个响应者
12.__block
和__weak
修饰符的区别
__block
不管是ARC还是MRC模式下都可以使用,可以修饰对象,还可以修饰基本数据类型。
__weak
只能在ARC模式下使用,也只能修饰对象,不能修饰基本数据类型
__block
对象可以在block中被重新复制,__weak
不可以。
13.ARC内部原理
ARC会自动帮我们插入retain
和release
语句。ARC编译器有两部分,分别是前端编译器和优化器。
1.前端编译器
前端编译器会为“拥有的”每一个对象插入相应的release
语句。如果对象的所有权修饰符是__strong
,那么它就是被拥有的。如果在某个方法内创建了一个对象,前端编译器会在方法末尾自动插入release
语句以销毁它。而类拥有的对象(实例变量/属性)会在dealloc
方法内被释放。事实上,你并不需要些dealloc方法或调用父类的dealloc
方法,ARC会自动帮你完成一切。此外,由编译器生成的代码甚至会比你自己写的release
语句的性能还要好,因为编译器可以做出一些假设。在ARC中,没有类可以覆盖release
方法,也没有调用它的必要。ARC会通过直接使用objc_release
来优化调用过程。而对于retain
也是同样的方法。ARC会调用objc_retain
来取代保留消息。
2.ARC优化器
虽然前端编译器听起来很厉害的样子,但代码中有时仍会出现几个对retain
和release
的重复调用。ARC优化器负责移除多余的retain
和release
语句,确保生成的代码运行速度高于手动引用计数的代码。
14.iOS ARC,IBOutlets strong与weak
在ARC中,一般outlet属性都推荐使用weak,而File's Owner链接到Nib的顶层对象应该使用strong。通俗一点说就是:如果你自定义的view,不是做为主视图的子视图直接显示,而是你自己实例化创建出来并加入主视图里的,那么你需要自己保留对象的所有权,需要使用strong。
15.UIView和CALayer区别和联系
1.UIView是UIKit的(只能iOS使用)CALayer是QuartzCore的(iOS和MacOS通用)
2.CALayer比UIView更加轻量级别,但是可以实现同样的效果
3.UIView比CALayer多了一个事件处理的功能,也就是说,CALayer不能处理用户的触摸事件,而UIView可以
4.UIView有个重要属性layer,可以返回它的主CALayer实例。CALayer *layer = myView.layer。
6.坐标系统:CALayer的坐标系统比UIView多了一个anchorPoint属性。
7.UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它。它本身完全是由CoreAnimation来实现的。它真正的绘图部分,是由一个CALayer类来管理 。UIView本身更像是一个CALayer的管理器,访问它的跟绘图和坐标有关的属性,例如frame,bounds等,实际上内部都是在访问它所包含的CALayer的相关属性。layer可以设置圆角显示(cornerRadius),也可以设置阴影(shadowColor)但是如果layer树中某个layer设置了圆角,树中所有layer的阴影效果都将不显示了。因此若是要有圆角又要阴影,变通方法只能做两个重叠的UIView,一个layer显示圆角,一个layer显示阴影。
8.渲染 当更新层,改变不能立即显示在屏幕上。当所有的层都准备好时,可以调用setNeedsDisplay方法来重绘显示。
9.变换 要在一个层中添加一个3D变换,可以分别设置层的transform或affineTransform属性。
10.变形Quartz Core的渲染能力,使二维图像可以被自由操纵,就好像是三维的。图像可以在一个三维坐标系中以任意角度被旋转,缩放和倾斜。CATransform3D的一套方法提供了一些魔术般的变换效果。
16.Runtime的消息机制
首先,编辑器将代码[obj makeText]转换为objc_msgSend(obj,@selector(makeText));在objc_msgSend函数中。首先通过obj的isa指针找到obj对应的class。在class中先去cache中 通过SEL查找对应函数method(猜测cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度),若cache中未找到。再去methodList中查找,若methodlist中未找到,则去superclass中查找。若能找到,则将method加入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中去执行。
网友评论