基礎題

weixin_34253539發表於2019-02-20

1 iOS基礎

1.1 父類實現深拷貝時,子類如何實現深度拷貝。父類沒有實現深拷貝時,子類如何實現深度拷貝。

深拷貝同淺拷貝的區別:淺拷貝是指標拷貝,對一個物件進行淺拷貝,相當於對指向物件的指標進行復制,產生一個新的指向這個物件的指標,那麼就是有兩個指標指向同一個物件,這個物件銷燬後兩個指標都應該置空。深拷貝是對一個物件進行拷貝,相當於對物件進行復制,產生一個新的物件,那麼就有兩個指標分別指向兩個物件。當一個物件改變或者被銷燬後拷貝出來的新的物件不受影響。

實現深拷貝需要實現NSCoying協議,實現- (id)copyWithZone:(NSZone *)zone 方法。當對一個property屬性含有copy修飾符的時候,在進行賦值操作的時候實際上就是呼叫這個方法。

父類實現深拷貝之後,子類只要重寫copyWithZone方法,在方法內部呼叫父類的copyWithZone方法,之後實現自己的屬性的處理

父類沒有實現深拷貝,子類除了需要對自己的屬性進行處理,還要對父類的屬性進行處理。

1.2 KVO,NSNotification,delegate及block區別

KVO就是cocoa框架實現的觀察者模式,一般同KVC搭配使用,通過KVO可以監測一個值的變化,比如View的高度變化。是一對多的關係,一個值的變化會通知所有的觀察者。

NSNotification是通知,也是一對多的使用場景。在某些情況下,KVO和NSNotification是一樣的,都是狀態變化之後告知對方。NSNotification的特點,就是需要被觀察者先主動發出通知,然後觀察者註冊監聽後再來進行響應,比KVO多了傳送通知的一步,但是其優點是監聽不侷限於屬性的變化,還可以對多種多樣的狀態變化進行監聽,監聽範圍廣,使用也更靈活。

delegate 是代理,就是我不想做的事情交給別人做。比如狗需要吃飯,就通過delegate通知主人,主人就會給他做飯、盛飯、倒水,這些操作,這些狗都不需要關心,只需要呼叫delegate(代理人)就可以了,由其他類完成所需要的操作。所以delegate是一對一關係。

block是delegate的另一種形式,是函數語言程式設計的一種形式。使用場景跟delegate一樣,相比delegate更靈活,而且代理的實現更直觀。

KVO一般的使用場景是資料,需求是資料變化,比如股票價格變化,我們一般使用KVO(觀察者模式)。delegate一般的使用場景是行為,需求是需要別人幫我做一件事情,比如買賣股票,我們一般使用delegate。

Notification一般是進行全域性通知,比如利好訊息一出,通知大家去買入。delegate是強關聯,就是委託和代理雙方互相知道,你委託別人買股票你就需要知道經紀人,經紀人也不要知道自己的顧客。Notification是弱關聯,利好訊息發出,你不需要知道是誰發的也可以做出相應的反應,同理發訊息的人也不需要知道接收的人也可以正常發出訊息。

1.3 KVC如果實現,如何進行鍵值查詢。KVO如何實現

請看這兩篇博文 KVC KVO

1.4 將一個函式在主執行緒執行的4種方法

GCD方法,通過向主執行緒佇列傳送一個block塊,使block裡的方法可以在主執行緒中執行。

dispatch_async(dispatch_get_main_queue(), ^{//需要執行的方法});

NSOperation 方法

NSOperationQueue*mainQueue = [NSOperationQueuemainQueue];//主佇列NSBlockOperation*operation = [NSBlockOperationblockOperationWithBlock:^{//需要執行的方法}];[mainQueue addOperation:operation];

NSThread 方法

[selfperformSelector:@selector(method)onThread:[NSThread mainThread]withObject:nilwaitUntilDone:YESmodes:nil];[selfperformSelectorOnMainThread:@selector(method)withObject:nilwaitUntilDone:YES];[[NSThread mainThread]performSelector:@selector(method)withObject:nil];

RunLoop方法

[[NSRunLoop mainRunLoop]performSelector:@selector(method) withObject:nil];

1.5 如何讓計時器呼叫一個類方法

計時器只能呼叫例項方法,但是可以在這個例項方法裡面呼叫靜態方法。

使用計時器需要注意,計時器一定要加入RunLoop中,並且選好model才能執行。scheduledTimerWithTimeInterval方法建立一個計時器並加入到RunLoop中所以可以直接使用。

如果計時器的repeats選擇YES說明這個計時器會重複執行,一定要在合適的時機呼叫計時器的invalid。不能在dealloc中呼叫,因為一旦設定為repeats 為yes,計時器會強持有self,導致dealloc永遠不會被呼叫,這個類就永遠無法被釋放。比如可以在viewDidDisappear中呼叫,這樣當類需要被回收的時候就可以正常進入dealloc中了。

[NSTimerscheduledTimerWithTimeInterval:1target:selfselector:@selector(timerMethod) userInfo:nilrepeats:YES];-(void)timerMethod{//呼叫類方法[[selfclass] staticMethod];}-(void)invalid{    [timer invalid];    timer =nil;}

1.6 如何重寫類方法

1、在子類中實現一個同基類名字一樣的靜態方法

2、在呼叫的時候不要使用類名呼叫,而是使用[self class]的方式呼叫。原理,用類名呼叫是早繫結,在編譯期繫結,用[self class]是晚繫結,在執行時決定呼叫哪個方法。

1.7 NSTimer建立後,會在哪個執行緒執行。

用scheduledTimerWithTimeInterval建立的,在哪個執行緒建立就會被加入哪個執行緒的RunLoop中就執行在哪個執行緒

自己建立的Timer,加入到哪個執行緒的RunLoop中就執行在哪個執行緒。

1.8 id和NSObject*的區別

id是一個 objc_object 結構體指標,定義是

typedefstructobjc_object *id

id可以理解為指向物件的指標。所有oc的物件 id都可以指向,編譯器不會做型別檢查,id呼叫任何存在的方法都不會在編譯階段報錯,當然如果這個id指向的物件沒有這個方法,該崩潰還是會崩潰的。

NSObject *指向的必須是NSObject的子類,呼叫的也只能是NSObjec裡面的方法否則就要做強制型別轉換。

不是所有的OC物件都是NSObject的子類,還有一些繼承自NSProxy。NSObject *可指向的型別是id的子集。

我的理解如果有錯漏請一定指出,非常感謝!

以下內容後續補充

iOS 核心框架

CoreAnimation

CoreGraphics

CoreLocation

AVFoundation

Foundation

iOS核心機制

UITableView 重用

ObjC記憶體管理;自動釋放池,ARC如何實現

runloop

runtime

Block的定義、特性、記憶體區域、如何實現

Responder Chain

NSOperation

GCD

資料結構

8大排序演算法

二叉樹實現

二分查詢實現

物件導向程式設計

封裝、繼承、多型

設計模式6個原則

設計一個類的功能,如何劃分粒度(單一職責)

介面隔離。

如果有一個鳥類,有飛的動作,一個鴕鳥繼承它是合適的嗎(里氏替換)

類之間的依賴如何依賴偶合度最小(依賴倒轉)

高層依賴低層,低層不能依賴高層。依賴介面,不能依賴具體的類。

如果A要呼叫C函式,但C是B的成員類,應該如何設計?(迪米特)

如何設計類,能做到只增加程式碼,而不修改程式碼,有哪些經驗(開放封閉)

通過設計模式解決。

計算機網路: TCP/IP、HTTPCDN、SPDY

電腦保安: RSA、AES、DES

作業系統:執行緒、程式、堆疊、死鎖、排程演算法

iOS新特性、新技術

iOS7 UIDynamic、SpritKit、新佈局、扁平化

iOS8 應用程式擴充套件、HealthKit、SceneKit、CoreLocation、TouchID、PhotoKit

第三方庫:SDWebImage、AFNetwork、JSONKit、wax


第二篇

1、KVO,NSNotification,delegate及block區別

  KVO就是cocoa框架實現的觀察者模式,一般同KVC搭配使用,通過KVO可以監測一個值的變化,比如View的高度變化。是一對多的關係,一個值的變化會通知所有的觀察者。

  NSNotification是通知,也是一對多的使用場景。在某些情況下,KVO和NSNotification是一樣的,都是狀態變化之後告知對方。NSNotification的特點,就是需要被觀察者先主動發出通知,然後觀察者註冊監聽後再來進行響應,比KVO多了傳送通知的一步,但是其優點是監聽不侷限於屬性的變化,還可以對多種多樣的狀態變化進行監聽,監聽範圍廣,使用也更靈活。

  delegate 是代理,就是我不想做的事情交給別人做。比如狗需要吃飯,就通過delegate通知主人,主人就會給他做飯、盛飯、倒水,這些操作,這些狗都不需要關心,只需要呼叫delegate(代理人)就可以了,由其他類完成所需要的操作。所以delegate是一對一關係。

  block是delegate的另一種形式,是函數語言程式設計的一種形式。使用場景跟delegate一樣,相比delegate更靈活,而且代理的實現更直觀。

  KVO一般的使用場景是資料,需求是資料變化,比如股票價格變化,我們一般使用KVO(觀察者模式)。delegate一般的使用場景是行為,需求是需要別人幫我做一件事情,比如買賣股票,我們一般使用delegate。

  Notification一般是進行全域性通知,比如利好訊息一出,通知大家去買入。delegate是強關聯,就是委託和代理雙方互相知道,你委託別人買股票你就需要知道經紀人,經紀人也不要知道自己的顧客。Notification是弱關聯,利好訊息發出,你不需要知道是誰發的也可以做出相應的反應,同理發訊息的人也不需要知道接收的人也可以正常發出訊息。

2、TableView滑動卡的的問題主要是因為:圖片的載入耗費過多時間,這時候應該在子執行緒中獲取影像資料,在主執行緒中賦值imageView即可。

  在子執行緒中不能更新UI,所有的UI更新都是在主執行緒中執行的。

  子執行緒中加入NSTimer的時候需要手動新增NSRunloop,否則不能迴圈

3、 _block 和 _weak 修飾符的區別

  _block不管是ARC和MRC模式下都可以使用,可以修飾物件,還可以修飾基本資料型別。

  _weak只能在ARC模式下使用,頁只能修飾物件(nsstring等),不能修飾基本資料型別(int等)。

  _block物件可以在block中被重新賦值,_weak不可以。

4、SDWebImage內部實現過程

1 入口 setImageWithURL:placeholderImage:options: 會先把 placeholderImage 顯示,然後 SDWebImageManager 根據 URL 開始處理圖片。

2 進入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交給 SDImageCache 從快取查詢圖片是否已經下載 queryDiskCacheForKey:delegate:userInfo:.

3 先從記憶體圖片快取查詢是否有圖片,如果記憶體中已經有圖片快取,SDImageCacheDelegate 回撥 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。

4 SDWebImageManagerDelegate 回撥 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示圖片。

5 如果記憶體快取中沒有,生成 NSInvocationOperation 新增到佇列開始從硬碟查詢圖片是否已經快取。

6 根據 URLKey 在硬碟快取目錄下嘗試讀取圖片檔案。這一步是在 NSOperation 進行的操作,所以回主執行緒進行結果回撥 notifyDelegate:。

7 如果上一操作從硬碟讀取到了圖片,將圖片新增到記憶體快取中(如果空閒記憶體過小,會先清空記憶體快取)。SDImageCacheDelegate 回撥 imageCache:didFindImage:forKey:userInfo:。進而回撥展示圖片。

8 如果從硬碟快取目錄讀取不到圖片,說明所有快取都不存在該圖片,需要下載圖片,回撥 imageCache:didNotFindImageForKey:userInfo:。

9 共享或重新生成一個下載器 SDWebImageDownloader 開始下載圖片。

10 圖片下載由 NSURLConnection 來做,實現相關 delegate 來判斷圖片下載中、下載完成和下載失敗。

11 connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進度載入效果。

12 connectionDidFinishLoading: 資料下載完成後交給 SDWebImageDecoder 做圖片解碼處理。

13 圖片解碼處理在一個 NSOperationQueue 完成,不會拖慢主執行緒 UI。如果有需要對下載的圖片進行二次處理,最好也在這裡完成,效率會好很多。

14 在主執行緒 notifyDelegateOnMainThreadWithInfo: 宣告解碼完,imageDecoder:didFinishDecodingImage:userInfo: 回撥給 SDWebImageDownloader。

15 imageDownloader:didFinishWithImage: 回撥給 SDWebImageManager 告知圖片下載完成。

16 通知所有的 downloadDelegates 下載完成,回撥給需要的地方展示圖片。

17 將圖片儲存到 SDImageCache 中,記憶體快取和硬碟快取同時儲存。寫檔案到硬碟也在以單獨 NSInvocationOperation 完成,避免拖慢主執行緒。

18 SDImageCache 在初始化的時候會註冊一些訊息通知,在記憶體警告或退到後臺的時候清理記憶體圖片快取,應用結束的時候清理過期圖片。

19 SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。

20 SDWebImagePrefetcher 可以預先下載圖片,方便後續使用。

從上面流程可以看出,當你呼叫setImageWithURL:方法的時候,他會自動去給你幹這麼多事,當你需要在某一具體時刻做事情的時候,你可以覆蓋這些方法。比如在下載某個圖片的過程中要響應一個事件,就覆蓋這個方法:

1//覆蓋方法,指哪打哪,這個方法是下載imagePath2的時候響應 2 3SDWebImageManager *manager = [SDWebImageManager sharedManager]; 4 5[manager downloadImageWithURL:imagePath2 options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) { 6 7NSLog(@"顯示當前進度"); 8 9} completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {1011NSLog(@"下載完成");1213}];

5、UIButton的父類是UIControl,UIControl的父類是UIView,UIView的父類是UIResponder。

相關文章