一、什麼是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