iOS知識點(一)

1. 什么是arc?(arc是為了解決什么問題誕生的?)

  • ARC的全稱是Automatic Reference Counting(自動引用計數)
  • ARC是自iOS 5之后增加的新特性,不需要程序員管理內容, 編譯器會在適當的地方自動給我們添加release/retain等代碼(主要針對內存泄露)

相關知識:
1.與ARC相對的是MRC, 手動引用計數, 可以簡稱MRC (Manual Reference Counting) 所有對象的內容都需要我們手動管理, 需要程序員自己編寫release/retain等代碼
2.ARC的判斷原則:只要沒有強指針指向對象,對象就會被釋放。
(1)強指針:默認的情況下,所有的指針都是強指針,關鍵字strong
(2)弱指針:_ _weak關鍵字修飾的指針
3.ARC的特點總結:
(1)不允許調用release,retain,retainCount
(2)允許重寫dealloc,但是不允許調用[super dealloc]
(3)@property的參數:
Strong:相當于原來的retain(適用于OC對象類型),成員變量是強指針
Weak:相當于原來的assign,(適用于oc對象類型),成員變量是弱指針
Assign:適用于非OC對象類型(基礎類型)

2. 請解釋以下keywords的區別: assign vs weak, __block vs__weak

  • weak和assign都是引用計算不變,兩個的差別在于,weak用于指針類型,而assign用于簡單的數據類型,如int BOOL 等。
  • assign看起來跟weak一樣,其實不能混用的,assign的變量在釋放后并不設置為nil(和weak不同),當你再去引用時候就會發生錯誤,崩潰,EXC_BAD_ACCESS.
  • __block 是通過引用來訪問self的實例變量,block也是一個強引用,self被retain,引起循環引用,用__weak是弱引用,當self釋放時,weakSelf已經等于nil

相關知識
在垃圾回收機制里面,如果你同時使用__weak__block來標識一個變量,那么該block將不會保證它是一直是有效的。 如果你在實現方法的時候使用了block,對象的內存管理規則更微妙:也是(__weak__block區別:)
(1)如果你通過引用來訪問一個實例變量,self會被retain。
(2)如果你通過值來訪問一個實例變量,那么變量會被retain

擴展:NSTimer注意避免循環引用的地方,需要找個合適的時機和地方來 invalidate timer
在引用計數的環境里面,默認情況下當你在block里面引用一個Objective-C對象的時候,該對象會被retain。當你簡單的引用了一個對象的實例變量時,它同樣被retain。但是被__block存儲類型修飾符標記的對象變量不會被retain

3. __block在arc和非arc下含義一樣嗎?

  • 對于非ARC下, 為了防止循環引用, 我們使用__block來修飾在Block中使用的對象:
  • 對于ARC下, 為了防止循環引用, 我們使用__weak來修飾在Block中使用的對象。原理就是:ARC中,Block中如果引用了__strong修飾符的自動變量,則相當于Block對該變量的引用計數+1。
    <解決循環引用問題>
//非ARC
__block typeof(self) weakSelf = self;
self.myBlock = ^(int paramInt){ 
//使用weakSelf訪問self成員
 [weakSelf anotherFunc];
};

4. 使用atomic一定是線程安全的嗎?

  • 當然不是。
    atomic在set方法里加了鎖,防止了多線程一直去寫這個property,造成難以預計的數值, 但這也只是讀寫的鎖定, 線程安全其實還是差一些。

atomic有個很大的問題是很慢,要比nonatomic慢20倍。
當然最后建議這種數值數值變化可以讓服務器來做

5. 描述一個你遇到過的retaincycle例子。

  • retain cycle 會造成內存溢出,嚴重情況會引起崩潰。一般注意點也不會發生,但在網絡連接比較多的地方就會不小心出現,vc異步的網絡請求,成功后的block調用vc,如果此時,用戶已經不用此vc了,vc還是沒有釋放。

一個下拉刷新,那個view和vc互相強引用,導致了沒釋放。view回去調用vc的scrollview的contentoffset

6. +(void)load; +(void)initialize;有什么用處?

  • 當類對象被引入項目時, runtime 會向每一個類對象發送 load 消息, 并且會在每一個類甚至分類被引入時僅調用一次,(調用的順序是父類優先于子類, 子類優先于分類) 而且每一個類中的 load 方法都不需要像 viewDidLoad 方法一樣調用父類的方法.

舉個例子:
由于 load 方法會在類被 import 時調用一次, 而這時往往是改變類的行為的最佳時機. 我在 DKNightVersion 中使用 method swizlling 來修改原有的方法時, 就是在分類 load 中實現的.

  • initialize 方法和 load 方法有一些不同, 它雖然也會在整個 runtime 過程中調用一次, 但是它是在該類的第一個方法執行之前調用, 也就是說 initialize 的調用是 <惰性> 的, 它的實現也與我們在平時使用的惰性初始化屬性時基本相同.

我在實際的項目中并沒有遇到過必須使用這個方法的情況, 在該方法中主要做 靜態變量的設置 并用于 確保在實例初始化前某些條件必須滿足 .

7. 為什么其他語言里叫函數調用,objective-c語言里則是給對象發消息(或者談下對runtime的理解)

  • 我們在其他語言中比如說: C, Python, Java, C++, Haskell ... 中提到函數調用或者方法調用(面向對象). 函數調用是在編譯期就已經決定了會調用哪個函數(方法), 編譯器在編譯期就能檢查出函數的執行是否正確.

**然而 Objective-C(ObjC) 是一門動態的語言, 整個 ObjC 語言都是盡可能的將所有的工作推遲到運行時才決定. 它基于 runtime 來工作, runtime 就是 ObjC 的靈魂, 其核心就是消息發送 objc_msgSend **

  • 所有的消息都會在運行時才會確定,[obj message]在運行時會被轉化為objc_msgSend(id self, SEL cmd, ...)來執行, 它會在運行時從 選擇子表中尋找對應的選擇子 并將選擇子與實現進行綁定. 而如果沒有找到對應的實現, 就會進入類似黑魔法的消息轉發流程. 調用 + (BOOL)resolveInstanceMethod:(SEL)aSelector方法, 我們可以在這個方法中 為類動態地生成方法 .

我們幾乎可以使用 runtime 修改 Objective-C 中的一切:
*class property object ivar method protocol *

8. 什么是methodswizzling?

  • method swizzling 實際上就是一種在運行時動態修改原有方法的技術, 它實際上是基于 ObjC runtime的特性, 而 method swizzling 的核心方法就是 method_exchangeImplementations(SEL origin, SEL swizzle)使用這個方法就可以在運行時動態地改變原有的方法實現

在DKNigtVersion (為iOS應用添加夜間模式) 中能夠看到大量 method swizzling 的使用, 方法的調用時機就是在上面提到的 load 方法中, 不在 initialize 方法中改變方法實現的原因是 initialize 可能會被子類所繼承并重新執行最終導致錯誤 , 而 load 并不會被繼承并重新執行.

9. UIView和CALayer是啥關系?

  • 每一個 UIView 的身后對應一個 Core Animation 框架中的 CALayer.

在 iOS 上 當你處理一個一個有一個的 UIView 時實際上是在操作 CALayer . 盡管有的時候你并不知道 (直接操作 CALayer 并不會在對效率有著顯著的提升).

  • UIView 實際上就是對 CALayer 的輕量級的封裝. UIView 繼承自 UIResponder 處理來自用戶的事件; CALayer 繼承自 NSObject 主要用于圖層的渲染和動畫. 設計原因:

1.你可以通過操作 UIView 在一個更高的層級上處理與用戶的交互, 觸摸, 點擊, 拖拽等事件, 這些都是在 UIKit 這個層級上完成的.
2.UIView 和 NSView(AppKit) 的實現極其不同, 而使用 Core Animation 可以實現底層代碼地重用, 因為在 Mac 和 iOS 平臺上都使用著近乎相同的 Core Animation 代碼, 這樣我們可以對這個層級進行抽象在兩種平臺上產生 UIKit 和 AppKit 用于不同平臺的框架.
3.使用 CALayer 的唯一原因大概是便于移植到不同的平臺, 如果僅僅使用 Core Animation 層級, 處理用戶的交互時間需要寫更多的代碼.

10. 如何高性能的給UIImageView加個圓角?
(不準說layer.cornerRadius!)

  • 一般情況下給 UIImageView 或者說 UIKit 的控件添加圓角都是改變 clipsToBounds 和 layer.cornerRadius, 這樣大約兩行代碼就可以解決. 但是, 這樣使用這樣的方法會 強制 Core Animation提前渲染屏幕的離屏繪制 , 而離屏繪制就會為性能帶來負面影響.

<貝塞爾曲線> 可以完美解決

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];  
imageView.center = CGPointMake(200, 300);  
UIImage *anotherImage = [UIImage imageNamed:@"image"];  
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);  
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds
  cornerRadius:50] addClip];
[anotherImage drawInRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();  
UIGraphicsEndImageContext();  
[self.view addSubview:imageView];

11. 使用drawRect有什么影響?(這個可深可淺,你至少得用過。。)

  • 這個方法的主要作用是根據傳入的 rect 來繪制圖像,我們還可以在這個方法中使用 Core Graphics 和 UIKit 來繪制視圖的內容.

  • 這個方法的調用機制也是非常特別. 當你調用 setNeedsDisplay 方法時, UIKit 將會把當前圖層標記為 dirty, 但還是會顯示原來的內容, 直到下一次的視圖渲染周期, 才會重新建立 Core Graphics 上下文, 然后將內存中的數據恢復出來, 使用 CGContextRef 進行繪制.

12. ASIHttpRequest或者SDWebImage里面給
UIImageView加載圖片的邏輯是什么樣的?(把
UIImageView放到UITableViewCell里面問更贊)

  • SDWebImage 中為 UIView 提供了一個分類叫做 WebCache, 這個分類中有一個最常用的接口, sd_setImageWithURL:placeholderImage: , 這個分類同時提供了很多類似的方法, 這些方法最終會調用一個同時具有 optionprogressBlockcompletionBlock 的方法, 而在這個類最終被調用的方法首先會檢查是否傳入了placeholderImage以及對應的參數,并設置
    placeholderImage

  • 然后獲取SDWebImageManager中的單例調用一個

    •          ``downloadImageWithURL:...``  的方法來獲取圖片, 而這個manager 獲取圖片的過程有大體上分為兩部分:
      

首先會在 SDWebImageCache 中尋找圖片是否有對應的緩存, 它會以 url 作為數據的索引先在內存中尋找是否有對應的緩存, 如果緩存未命中就會在磁盤中利用 MD5 處理過的 key 來繼續查詢對應的數據, 如果找到了, 就會把磁盤中的緩存備份到內存中.

然而, 假設我們在內存和磁盤緩存中都沒有命中, 那么manager就會調用 SDWebImageDownloader 對象的方法downloadImageWithURL:...來下載圖片, 過程中調用另一個方法:
addProgressCallback:andCompletedBlock:fotURL:createCallback:來存儲下載過程中和下載完成的回調, 當回調塊是第一次添加的時候, 方法會實例化一個 NSMutableURLRequest 和 SDWebImageDownloaderOperation , 并將后者加入 downloader 持有的下載隊列開始圖片的異步下載.

  • 而在圖片下載完成之后, 就會在主線程設置 image, 完成整個圖像的異步下載和配置.

13. 麻煩你設計個簡單的圖片內存緩存器(移除策略是一定要說的)

圖片的內存緩存,可以考慮將圖片數據保存到一個數據模型中。所以在程序運行時這個模型都存在內存中。
移除策略:釋放數據模型對象。

14. 講講你用Instrument優化動畫性能的經歷吧(別問我什么是Instrument)

考慮程序的性能,可以借助數據化圖形化的輸出方式。與其花費時間在優化小細節上不如多點時間找到你改優化的地方.時間事件查看器 ——> Time Profiler打開Instrument的步驟:xcode ——> open developer Tool ——> instrument 選取相應的strumnet的工具,選擇相應的strument里面的工具,然后選擇模擬器或者真機上面的應用,點擊右上角的開始按鈕,然后就可以看到相應內容

Instrument詳細介紹

15. loadView是干嘛用的?

  • 當你訪問一個ViewController的view屬性時,如果此時view的值是nil,那么,ViewController就會自動調用loadView這個方法。這個方法就會加載或者創建一個view對象,賦值給view屬性。

loadView默認做的事情是:如果此ViewController存在一個對應的nib文件,那么就加載這個nib。否則,就創建一個UIView對象。
如果你用Interface Builder來創建界面,那么不應該重載這個方法。
如果你想自己創建view對象,那么可以重載這個方法。此時你需要自己給view屬性賦值。你自定義的方法不應該調用super。如果你需要對view做一些其他的定制操作,在viewDidLoad里面去做。

  • 根據上面可以知道,有兩種情況:

1、如果你用了nib文件,重載這個方法就沒有太大意義。因為loadView的作用就是加載nib。如果你重載了這個方法不調用super,那么nib文件就不會被加載。如果調用了super,那么view已經加載完了,你需要做的其他事情在viewDidLoad里面做更合適。
2、如果你沒有用nib,這個方法默認就是創建一個空的view對象。如果你想自己控制view對象的創建,例如創建一個特殊尺寸的view,那么可以重載這個方法,自己創建一個UIView對象,然后指定 self.view = myView; 但這種情況也沒有必要調用super,因為反正你也不需要在super方法里面創建的view對象。如果調用了super,那么就是浪費了一些資源而已

16. viewWillLayoutSubView你總是知道的。

橫豎屏切換的時候,系統會響應一些函數,其中
viewWillLayoutSubviews 和 viewDidLayoutSubviews。

- (void)viewWillLayoutSubviews  {   
   [self _shouldRotateToOrientation:(UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation];  
}  
-(void)_shouldRotateToOrientation:(UIDeviceOrientation)orientation {  
   if (orientation == UIDeviceOrientationPortrait ||orientation ==UIDeviceOrientationPortraitUpsideDown) {
// 豎屏 }
 else {
// 橫屏     } 
}
- (NSUInteger)supportedInterfaceOrientations{
    // 切換橫屏
    return UIInterfaceOrientationMaskLandscape;
}

通過上述一個函數就知道橫豎屏切換的接口了。
注意:viewWillLayoutSubviews只能用在ViewController里面,在view里面沒有響應。

17. GCD里面有哪幾種Queue?你自己建立過串行queue嗎?背后的線程模型是什么樣的?

  • 1.主隊列 dispatch_main_queue(); 串行 ,更新UI
    2.全局隊列 dispatch_global_queue(); 并行,四個優先級:background,low,default,high
    3.自定義隊列 dispatch_queue_t queue ; 可以自定義是并行:DISPATCH_QUEUE_CONCURRENT
    或者串行DISPATCH_QUEUE_SERIAL

18. 用過coredata或者sqlite嗎?讀寫是分線程的嗎?遇到過死鎖沒?咋解決的?

  • 數據庫讀取操作一般都是多線程訪問的。在對數據進行讀取時,我們要保證其當前狀態不能被修改,即讀取時加鎖,否則就會出現數據錯誤混亂。
    IOS中常用的兩種數據持久化存儲方式:CoreData和SQLite,兩者都需要設置線程安全

19. http的post和get啥區別?(區別挺多的,麻煩多說點)

GET和POST與數據如何傳遞沒有關系, GET和POST是由HTTP協議定義的。在HTTP協議中,Method和Data(URL, Body, Header)是正交的兩個概念,也就是說,使用哪個Method與應用層的數據如何傳輸是沒有相互關系的。HTTP沒有要求,如果Method是POST數據就要放在BODY中。也沒有要求,如果Method是GET,數據(參數)就一定要放在URL中而不能放在BODY中.

  • 1.(1) GET請求的數據會附在URL之后(就是把數據放置在HTTP協議頭中),以?分割URL和傳輸數據,參數之間以&相連,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5%A5%BD。如果數據是英文字母/數字,原樣發送,如果是空格,轉換為+,如果是中文/其他字符,則直接把字符串用BASE64加密,得出如:%E4%BD%A0%E5%A5%BD,其中%XX中的XX為該符號以16進制表示的ASCII。
    (2) POST把提交的數據則放置在是HTTP包的包體中。
  • 2 . HTTP協議對GET和POST都沒有對長度的限制

(1).首先是”GET方式提交的數據是有字節限制的”,因為GET是通過URL提交數據,那么GET可提交的數據量就跟URL的長度有直接關系了。其限制取決于操作系統的支持。
  注意這是限制是整個URL長度,而不僅僅是你的參數值數據長度。
 (2).理論上講,POST是沒有大小限制的,HTTP協議規范也沒有進行大小限制,POST數據是沒有限制的,起限制作用的是服務器的處理程序的處理能力。

  • 3.POST的安全性要比GET的安全性高,其實沒有絲毫關系。對于GET和POST的理解,是純粹地來源于HTTP協議。他們只有一點根本區別,簡單點兒說,一個用于獲取數據,一個用于修改數據

20. 我知道你大學畢業過后就沒接觸過算法數據結構了,但是請你一定告訴我什么是Binary search tree? search的時間復雜度是多少?我很想知道!

  • Binary search tree:二叉搜索樹。
    主要由四個方法:(用C語言實現或者Python)
    1.search:時間復雜度為O(h),h為樹的高度
    2.traversal:時間復雜度為O(n),n為樹的總結點數。
    3.insert:時間復雜度為O(h),h為樹的高度。
    4.delete:最壞情況下,時間復雜度為O(h)+指針的移動開銷。

可以看到,二叉搜索樹的dictionary operation的時間復雜度與樹的高度h相關。所以需要盡可能的降低樹的高度,由此引出平衡二叉樹Balanced binary tree。它要求左右兩個子樹的高度差的絕對值不超過1,并且左右兩個子樹都是一棵平衡二叉樹。這樣就可以將搜索樹的高度盡量減小。常用算法有紅黑樹、AVL、Treap、伸展樹等。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內容

  • iOS網絡架構討論梳理整理中。。。 其實如果沒有APIManager這一層是沒法使用delegate的,畢竟多個單...
    yhtang閱讀 5,231評論 1 23
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,196評論 30 471
  • 基礎 1. 為什么說Objective-C是一門動態的語言? 2. 講一下MVC和MVVM,MVP? 3. 為...
    波妞和醬豆子閱讀 3,351評論 0 46
  • 1.屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作...
    曾令偉閱讀 1,077評論 0 10
  • cookie cookie是什么?用來保存用戶信息 自動登錄、記住用戶名 cookie的特性 1.同一個網站所有頁...
    pizan閱讀 276評論 0 0