标签:
1、什么是ARC?
ARC(Automatic Reference Counting )自动应用计数器,代码自动添加的release/retain,原先是需要手动添加的用来处理内存管理的应用计数的代码可以自动的由编译器完成了。ARC是为解决内存管理而诞生的。
2、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即可)
4.使用atomic一定是线程安全的吗?
这个问题很少遇到,但是答案当然不是。
atomic在set方法里加了锁,防止了多线程一直去写这个property,造成难以预计的数值。但这也只是读写的锁定。跟线程安全其实还是差一些。看下面。
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的时候之后,会重新绘制,很多这样的按钮的话就会比较影响效率。以下都会被调用
1、如果在UIView初始化时没有设置rect大小,将直接导致drawRect不被自动调用。drawRect 掉用是在Controller->loadView, Controller->viewDidLoad 两方法之后掉用的.所以不用担心在 控制器中,这些View的drawRect就开始画了.这样可以在控制器中设置一些值给View(如果这些View draw的时候需要用到某些变量 值).
2、该方法在调用sizeToFit后被调用,所以可以先调用sizeToFit计算出size。然后系统自动调用drawRect:方法。
3、通过设置contentMode属性值为UIViewContentModeRedraw。那么将在每次设置或更改frame的时候自动调用drawRect:。
4、直接调用setNeedsDisplay,或者setNeedsDisplayInRect:触发drawRect:,但是有个前提条件是rect不能为0。
11.SDWebImage里面给UIImageView加载图片的逻辑是什么样的?
非常非常喜欢SDWebImage,就算后来AF也做了图片缓存,我也还是一直使用。图片缓存真的是一件令人头疼的事,但是SDWebImage封装了一切,你所需要的只是简单的set一个URL;
1、设置一个展位图(可选择);
2、根据URL去内存中找,找到返回图片
3、内存找不到,硬盘找,找到返回图片,内存做备份
4、硬盘还找不到,去下载,返回图片,并进行存储(硬盘,内存)。
其中有几点技术细节比较重要,
1、图片在内存中是key-value的方式。
2、在硬盘中是data的方式,imageWithData方法获取。
3、key-value方式是url的MD5。
4、注册内存和硬盘通知,如果很吃紧,就删除部分。
很多技术细节,要看源码。
12.loadView是干嘛用的?
viewController的方法,会在viewDidLoad之前进行调用。
很多人都会疑惑self.view,这个view道理是哪里来的,就是在这里。一般不需要去操作这个。但如果有特殊的需求,要求这个self.view是我们自己自定义的view时候就可以用这个方法,
MyView *myview = [[MyView alloc]init];
self.view = myview;
像上面一样重写一下就行了。
切记:不要自己调用-loadView -viewDidLoad
标签:
原文地址:http://www.cnblogs.com/baidaye/p/5201707.html