標籤:
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
View Code
但是如果有個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];
View Code
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();
View Code
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
13.viewWillLayoutSubView當viewController的bounds又改變,調用這個方法來實現subview的位置。可重寫這個方法來實現父視圖變化subview跟著變化。
14.GCD裡面有哪幾種Queue?你自己建立過串列queue嗎?背後的執行緒模式是什麼樣的?1.主隊列 dispatch_main_queue(); 串列 ,更新UI
2.全域隊列 dispatch_global_queue(); 並行,四個優先順序:background,low,default,high
3.自訂隊列 dispatch_queue_t queue ; 可以自訂是並行:
iOS 知識點