一、什么是ARC? ios
ARC(Automatic Reference Counting )自动应用计数器,代码自动添加的release/retain,原先是须要手动添加的用来处理内存管理的应用计数的代码能够自动的由编译器完成了。ARC是为解决内存管理而诞生的。swift
二、assign 和 weak,_block 和 _weak 的区别?缓存
strong 和 weak 是在arc后引入的关键字,strong相似于retain,引用时候会引用计算+1,weak相反,不会改变引用计数。weak和assign都是引用计算不变,两个的差异在于,weak用于object type,就是指针类型,而assign用于简单的数据类型。安全
block 不能修改局部变量,若是须要修改须要加上block.
block 会对对象强引用,引发retain-cycle,须要使用weak服务器
__weak __typeof(&*self)weakSelf =self;
在block种使用weakSelf可避免这种强引用。
(两个指针,指向同一块地址(self));网络
3.__block在arc和非arc下含义多线程
通常在block中修改变量都须要事先加block进行修饰。
在非arc中,block修饰的变量的引用计算是不变的。
在arc中,会引用到,而且计算+1;
非arc下可以使用(arc直接使用__weak便可)iphone
4.使用atomic必定是线程安全的吗?异步
这个问题不多遇到,可是答案固然不是。
atomic在set方法里加了锁,防止了多线程一直去写这个property,形成难以预计的数值。但这也只是读写的锁定。跟线程安全其实仍是差一些。看下面。ide
1 @interface MONPerson : NSObject 2 @property (copy) NSString * firstName; 3 @property (copy) NSString * lastName; 4 - (NSString *)fullName; 5 @end 6 7 Thread A: 8 p.firstName = @"Rob"; 9 Thread B: 10 p.firstName = @"Robert"; 11 Thread A: 12 label.string = p.firstName; // << uh, oh -- will be Robert
可是若是有个C也在写,D在读取,D会读到一些随机的值(ABC修改的值),这就不是线程安全的了。最好的方法是使用lock。
1 Thread A: 2 [p lock]; // << wait for it… … … … 3 // Thread B now cannot access 4 pp.firstName = @"Rob"; 5 NSString fullName = p.fullName; 6 [p unlock]; 7 // Thread B can now access plabel.string = fullName; 8 9 Thread B: 10 [p lock]; // << wait for it… … … … 11 // Thread A now cannot access p… 12 [p unlock];
atomic有个很大的问题是很慢,要比nonatomic慢20倍。
固然最后建议这种数值数值变化可让服务器来作。
5.一个遇到过的retain cycle例子
retain cycle 会形成内存溢出,严重状况会引发崩溃。通常注意点也不会发生,但在网络链接比较多的地方就会不当心出现,vc异步的网络请求,成功后的block调用vc,若是此时,用户已经不用此vc了,vc仍是没有释放。
曾近本身写过一个下拉刷新,那个view和vc互相强引用,致使了没释放。view回去调用vc的scrollview的contentoffset。
6.+(void)load; +(void)initialize;有什么用处?
两个方法均可以进行一些类的初始化操做。其中有些小区别。
+(void)load 方法只要加入了工程种,进行了编译,且.m中实现了这个方法,都会调用一次,值得注意的时没实现的子类是不会调用的,就算父类实现了也不行。categories,都实现了这个方法,只会调用其中一个,具备不肯定性。
+(void)initialize 在发送第一条消息给类的时候进行调用,跟load方法的不一样之处在于,比较迟,可实现懒加载,且父类.m实现了该方法,子类不实现也会调用父类,跟正常的方法同样。
7.什么是method swizzling?
其实跟字面的意思很相近。方法的调和。能够去修改oc中两个方法的调用。
这张图看起来会比较形象
具体的作法,
首先,用Categroy创建本身的方法。
在+load方法中去实现方法交换的代码(load能够保证被调用,其余方法都不靠谱)
Method ori_Method = class_getInstanceMethod([MYclass class], @selector(lastObject)); Method my_Method = class_getInstanceMethod([MYclass class], @selector(myLastObject)); method_exchangeImplementations(ori_Method, my_Method);
必定要记住,你的方法实现已经变了。
8.UIView和CALayer是啥关系?
view是对layer的一种封装,你对view的不少操做事实上是对layer的操做,之因此会出现这两个东西是由于
view支持不少手势的交互,你所操做iphone的各类点击,拖动等等。
layer来至于mac os,是能够跨平台的东西。这里就是个很要学问的东西,系统的可变部分和不可变部分,可变部分越多,系统越不稳定,可是功能就更加丰富。layer就是做为一种不可变的东西存在,view做为一种可变的东西存在,全部咱们每次在ios更新时候得到了大量的view新特性,可是整个view系统底层不少东西依旧能够接着使用,各类动画等。这就是分开view和layer的功劳。一言以蔽之
Simply speaking,UIView inherit from NSResponder,handle events from users, contains CALayer,which inherit from NSObject,mainly focus on rendering,animation etc.
9.如何高性能的给UIImageView加个圆角
其实你只须要的时圆角图片。。。。。
1 UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale); 2 [[UIBezierPath bezierPathWithRoundedRect:RECT cornerRadius:RADIUS] addClip]; 3 [image drawInRect:RECT]; 4 UIImage* imageNew = UIGraphicsGetImageFromCurrentImageContext(); 5 UIGraphicsEndImageContext();
10.使用drawRect有什么影响?
用来画图,这个方法会在intiWithRect时候调用。
这个方法的影响在于有touch event的时候以后,会从新绘制,不少这样的按钮的话就会比较影响效率。如下都会被调用
一、若是在UIView初始化时没有设置rect大小,将直接致使drawRect不被自动调用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 两方法以后掉用的.因此不用担忧在 控制器中,这些View的drawRect就开始画了.这样能够在控制器中设置一些值给View(若是这些View draw的时候须要用到某些变量 值).
二、该方法在调用sizeToFit后被调用,因此能够先调用sizeToFit计算出size。而后系统自动调用drawRect:方法。
三、经过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
四、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,可是有个前提条件是rect不能为0。
11.SDWebImage里面给UIImageView加载图片的逻辑是什么样的?
很是很是喜欢SDWebImage,就算后来AF也作了图片缓存,我也仍是一直使用。图片缓存真的是一件使人头疼的事,可是SDWebImage封装了一切,你所须要的只是简单的set一个URL;
一、设置一个展位图(可选择);
二、根据URL去内存中找,找到返回图片
三、内存找不到,硬盘找,找到返回图片,内存作备份
四、硬盘还找不到,去下载,返回图片,并进行存储(硬盘,内存)。
其中有几点技术细节比较重要,
一、图片在内存中是key-value的方式。
二、在硬盘中是data的方式,imageWithData方法获取。
三、key-value方式是url的MD5。
四、注册内存和硬盘通知,若是很吃紧,就删除部分。
不少技术细节,要看源码。
12.loadView是干吗用的?
viewController的方法,会在viewDidLoad以前进行调用。
不少人都会疑惑self.view,这个view道理是哪里来的,就是在这里。通常不须要去操做这个。但若是有特殊的需求,要求这个self.view是咱们本身自定义的view时候就能够用这个方法,
MyView *myview = [[MyView alloc]init]; self.view = myview;
像上面同样重写一下就好了。
切记:不要本身调用-loadView -viewDidLoad