iOS面試建議

定時器相關的問題

  • 定時器的模式問題是被問的最多的

UIScrollView(UITableView) 拖動時執行的是 UITrackingRunLoopMode,會導致暫停定時器,等恢復為 NSDefaultRunLoopMode 時才恢復定時器。
所以如果需要定時器在UIScrollView 拖動時也不影響的話,建議添加到UITrackingRunLoopModeNSRunLoopCommonModes 中:

NSTimer *timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode]; ///< 或者 NSRunLoopCommonModes
  • 自動添加到當前NSRunLoop的方式,這種方式會導致滑動過程中定時器失效的問題,解決方式就是用(1)的方式設定NSRunLoop模式
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(test) userInfo:nil repeats:YES];
  • 定時器相關API的含義,沒用過的可能會誤解
[myTimer invalidate]; // 廢棄定時器 ,是永久的停止,移除定時器對象
[myTimer setFireDate:[NSDate distantFuture]]; // 關閉定時器;遙遠的將來才能觸發,功能相當于關閉
[myTimer setFireDate:[NSDate distantPast]]; // 開啟定時器;很久很久以前就觸發了,功能相當于開啟
  • GCD中的延時執行,相當于定時效果
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC);
dispatch_after(timer, dispatch_get_main_queue(), ^(void) {
    NSLog(@"GCD-----%@",[NSThread currentThread]);
});
  • NSRunLoop結合起來用,定時器是一種中斷源,知道這個的,基本上做得比較底層了,在實際工作中,還沒怎么遇到
@property (nonatomic ,strong)dispatch_source_t timer;//  注意:此處應該使用強引用 strong
{
    //0.創建隊列
    dispatch_queue_t queue = dispatch_get_main_queue();
    //1.創建GCD中的定時器
    /*
     第一個參數:創建source的類型 DISPATCH_SOURCE_TYPE_TIMER:定時器
     第二個參數:0
     第三個參數:0
     第四個參數:隊列
     */
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

    //2.設置時間等
    /*
     第一個參數:定時器對象
     第二個參數:DISPATCH_TIME_NOW 表示從現在開始計時
     第三個參數:間隔時間 GCD里面的時間最小單位為 納秒
     第四個參數:精準度(表示允許的誤差,0表示絕對精準)
     */
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);

    //3.要調用的任務
    dispatch_source_set_event_handler(timer, ^{
        NSLog(@"GCD-----%@",[NSThread currentThread]);
    });

    //4.開始執行
    dispatch_resume(timer);

    //
    self.timer = timer;
}

此處注意一定要強引用定時器 ,否則定時器執行到}后將會被釋放,無定時效果。
GCD定時器時間非常精準,最小的定時時間可以達到1納秒,所以用在非常精確的定時場合。

多線程相關問題

  • 串行隊列和并行隊列概念,同步執行和異步執行概念
NSLog(@"開始");
dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"進行中");
});
NSLog(@"結束");

這段代碼:只會打印第一句:開始,然后主線程就卡死了。
能回答這個問題并作出解釋,說明對這個問題了解比較透徹了。

相對基礎一點的問題:比較容易混淆
(1)dispatch_queue_t queue = dispatch_queue_create ( "com.dispatch.serial" , DISPATCH_QUEUE_SERIAL );是串行隊列還是并行隊列?
dispatch_queue_t queue = dispatch_queue_create ( "com.dispatch.serial" , DISPATCH_QUEUE_CONCURRENT );是串行隊列還是并行隊列?
(2)dispatch_get_main_queue()是串行的還是并行的?
(3)dispatch_get_global_queue()是串行的還是并行的?
(4)dispatch_sync()是同步執行還是異步執行?
(5)dispatch_async()是同步執行還是異步執行?

  • n個異步任務都執行完畢后再執行下一步的場景

圖片很大,需要分3次下載,然后合并才能用,應該怎么做?

通過dispatch_group_t來實現,將每部分圖片下載請求放入到Group中,將合并圖片的操作放在dispatch_group_notify中實現。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*下載圖片Part1 */ });
dispatch_group_async(group, queue, ^{ /*下載圖片Part2 */ });
dispatch_group_async(group, queue, ^{ /*下載圖片Part3 */ }); 
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    // 合并圖片
});
  • 任務間依賴的場景

有3 個任務:A: 從服務器上下載一張圖片,B:給這張圖片加個水印,C:把圖片返回給服務器。如何實現?

//1.任務一:下載圖片
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"下載圖片");
}];

//2.任務二:打水印
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"打水印");
}];

//3.任務三:上傳圖片
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"上傳圖片");
}];

//4.設置依賴
[operation2 addDependency:operation1];      //任務二依賴任務一
[operation3 addDependency:operation2];      //任務三依賴任務二

//5.創建隊列并加入任務
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];
  • iOS中多線程技術的種類以及選擇

(1)NSOperation & NSOperationQueue :是對GCD的對象化封裝,并且有cancel功能,推薦使用
(2)CGD:至少要知道模板型使用方式

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{   
    // 耗時的操作   
    dispatch_async(dispatch_get_main_queue(), ^{   
        // 更新界面   
    });   
});

(3)NSThread:控制力更強一點,比較底層了,用得不多。一些常用的方法可以問問,比如start,cancel,sleepForTimeInterval等等。
(4)NSObject就有的方法performSelectorInBackground,swift中這個方法被取消了
(5)pthread,知道這個的,c應該不錯

  • 線程同步方式,在實際編程中遇到不多,但是概念比較重要

(1)NSLock方式

   [xxxlock lock] //上鎖

  同步代碼塊

  [xxxlock unlock]//解鎖

(2)NSCondition方式

   [xxxCondition lock] //上鎖

  同步代碼塊

  [xxxCondition unlock]//解鎖

(3)@synchronized( 同一對象) 一般是self;這個使用方便,但是很耗資源

   @synchronized(self){

  線程執行代碼;

  }

(4)OSSpinLock自旋鎖,atomic關鍵字,GCD串行隊列,循環鎖NSRecursiveLock,pthreadmutex,信號量等等

本地存儲,本地緩存

  • 沙盒的目錄結構,使用場合
    Application:存放程序源文件,上架前經過數字簽名,上架后不可修改
    Documents: 保存應?運行時生成的需要持久化的數據,iTunes同步設備時會備份該目 錄。例如,游戲應用可將游戲存檔保存在該目錄
    tmp: 保存應?運行時所需的臨時數據,使?完畢后再將相應的文件從該目錄刪除。應用 沒有運行時,系統也可能會清除該目錄下的文件。iTunes同步設備時 不會備份該目錄
    Library/Caches: 保存應用運行時?成的需要持久化的數據,iTunes同步設備時不會備份 該目錄。?一般存儲體積大、不需要備份的非重要數據,比如網絡數據緩存存儲到Caches
    Library/Preference: 保存應用的所有偏好設置,如iOS的Settings(設置) 應?會在該目錄中查找應?的設置信息。iTunes同步設備時會備份該目錄

  • 數據持久化方案
    (1)plist屬性列表存儲(如NSUserDefaults
    (2)文件存儲(如二進制數據寫入文件存儲,通過NSFileManager來操作將下載起來的二進制數據寫入文件中存儲)
    (3)NSKeydeArchiver歸檔存儲, === 這個要實現NSCoding協議,model要實現哪兩個函數?這點在實際使用中也可能忘記
    (4)數據庫SQLite3存儲(如FMDB、Core Data)=== 直接用SQL語句和CoreData的區別,CoreData的“坑”
    (5)KeyChain,用戶名密碼 === 代碼怎么實現?需要導入哪幾個系統framework

  • SDWebImage的原理,或者其他圖片緩存庫
    (1)從內存中(字典)找圖片(當這個圖片在本次程序加載過),找到直接使用;
    (2)從沙盒中找,找到直接使用,緩存到內存。
    (3)從網絡上獲取,使用,緩存到內存,緩存到沙盒。

  • YYCache的原理,或者其他緩存庫的原理
    (1)內存緩存
    (2)硬盤緩存
    (3)key-value的方式,支持對象
    (4)本質還是sqlite數據庫和NSFile文件系統;20K閾值,內容少用數據庫,內容多用文件,綜合性能最高
    (5)更新邏輯:設定時間和體積。隊列方式,最新使用的,新加入,需要優先的放隊列首部。更新時,先從隊列尾部刪除

  • NSURLCache、NSURLRequest本身的緩存機制,AFNetworking用的是這一套。==== 這個用得不多,了解這些細節的不多,比較難

(1)獲得全局緩存對象(沒必要手動創建)

NSURLCache *cache = [NSURLCache sharedURLCache]; 

(2)設置內存緩存的最大容量(字節為單位,默認為512KB)

- (void)setMemoryCapacity:(NSUInteger)memoryCapacity;

(3)設置硬盤緩存的最大容量(字節為單位,默認為10M)

- (void)setDiskCapacity:(NSUInteger)diskCapacity;

(4)硬盤緩存的位置:沙盒/Library/Caches

(5)取得某個請求的緩存

- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request; 

(6)清除某個請求的緩存

- (void)removeCachedResponseForRequest:(NSURLRequest *)request;

(7)清除所有的緩存

- (void)removeAllCachedResponses;
NSURLRequestUseProtocolCachePolicy // 默認的緩存策略(取決于協議)

NSURLRequestReloadIgnoringLocalCacheData // 忽略緩存,重新請求

NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未實現

NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 忽略緩存,重新請求

NSURLRequestReturnCacheDataElseLoad// 有緩存就用緩存,沒有緩存就重新請求

NSURLRequestReturnCacheDataDontLoad// 有緩存就用緩存,沒有緩存就不發請求,當做請求出錯處理(用于離線模式)

NSURLRequestReloadRevalidatingCacheData // 未實現

Http協議header字段,比如max-age,ETag,Last-Modified等字段的含義
  • UIWebView,WKWebView清理緩存的機制?
    WKWebView從iOS8推出,但是清理緩存的API要從iOS9開始

屬性修飾符

  • block中修飾外面變量的修飾符? __block

  • 打破引用循環的關鍵字? weak;會自動設為nil,防止崩潰;如果能解釋清楚自動設nil的原理,是高手

  • 默認的關鍵字?strong

  • nonatomic? 非線程安全,加快速度。

  • atomic? 對setter加鎖,用@synchronized加鎖,耗性能;對getter不加鎖,不能做到“真正的線程安全”

  • assign、weak、unsafe_unretained的區別? assign用于基礎類型,“如果用于對象,不會設為nil,會導致野指針,會帶來崩潰”

  • copy?NSString,NSArray,NSDictionary,NSSet等。引用計數對這些集合類型無意義

block引用循環

  • 解決的方案weakSelf
 __weak __typeof(self)weakSelf = self;
[self.context performBlock:^{
     __strong __typeof(weakSelf)strongSelf = weakSelf; 
    [strongSelf doSomething];
    [strongSelf doMoreThing];
} ];
  • strongSelf的原因? 為了防止事情還沒做完,weakSelf就變成了nil

  • block不需要用weakSelf的場合?
    動畫的時候不需要,比如

self.alpha = 0;
[UIView animateWithDuration:0.2 animations:^ {
    self.alpha = 1;
}]

runtime動態特性

  • NSString *obj = [[NSSData alloc]init] ,obj在編譯時和運行時分別是什么類型的對象?
    編譯時是NSString, 運行時是NSSData的一個實例
  1. 字典轉模型的原理?第三方庫?
    YYModel
    屬性列表,class_copyPropertyList

  2. 不埋點統計,怎么做到? 熱更新JSPatch的原理?
    方法交換 Method Swizzling class_getInstanceMethod() method_exchangeImplementations()

  3. 如何給類別category添加屬性?
    關聯對象
    objc_setAssociatedObject objc_getAssociatedObject

  4. 如何在不創建類的前提下調用類的方法?用URL處理函數調用
    NSClassFromString()這個函數可以把URL中的字符串轉化為本地定義的類
    performSelector方法執行相應的方法

Native和H5的交互方式

(1)截取URL,定義scheme,做相應處理
(2)JavaScriptCore框架jsContext,使用注入的方法
(3)WKWebView的注入方式

第三方庫WebViewJavascriptBridge使用的是截取URL的方式,對UIWebViewWKWebView都適用

深復制,淺復制

NSArray *array = @[@"a", @"b", @"c", @"d"];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
  1. copyArrayarray的地址是否一樣? 一樣
  2. mCopyArrayarray的地址又是否一樣? 不一樣
  3. 改變mCopyArray里面的元素內容,是否會刻變array的內容? 不改變
  4. copymutableCopy的拷貝操作有何不同?
    copy淺拷貝,只是指針的復制,而內容未復制;
    mutableCopy是深拷貝,復制內容,新分配一段內存;

iOS架構

MVC
MVVM
MVP
VIPER

NSArray的實現方式?

指針的數組

需要區分流量來自哪個渠道,怎么做?

提升表格性能的方法?

(1)無用的網絡請求及時取消
(2)表格cell重用
(3)提前算好cell的高度
(4)圓角不要用cornerRadius

Https和Http的區別?

Https == http + socket + TLS
iOS9開始,XCode默認用Https
如何繼續用Http?在plist中將某個字段打開
企業版賬號發布時,ipa包可以http的,但是那個plist文件是需要https的,不然不能自動安裝程序

bitCode

從iOS9開始
好處是降低安裝包的大小
蘋果后臺根據用戶手機,只下傳必要的圖片

在ViewDidLoad中設置frame有什么問題?

UIImageView實現圓角的方法?

(1)Qurarz
(2)layerCornerRadius
(3)用path

連接藍牙要注意些什么?

iOS中提供一個單例用于藍牙相關的函數
(1)廣播,用于掃描設備,選中特定設備
(2)建立點對點連接
(3)協議一般開頭是兼容微信的頭部,然后是自己的頭部,然后是數據
(4)數據要按照一定的大小進行分包,每次傳輸的大小是受限的
(5)數據是NSData的,轉化為有意義的自定義類型時要注意大端和小端字節序的問題
(6)傳輸時有奇偶校驗的事情,要跟firmware端的約定好
(7)丟包重傳,定時重連,空中升級等等都是比較令人頭疼的內容

Object-C的一些容易誤解的特性

  • 下面的代碼輸出什么?
@implementation Son : Father

- (id)init {
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}

@end

// 輸出
NSStringFromClass([self class]) = Son
NSStringFromClass([super class]) = Son

這個題目主要是考察關于Objective-C中對selfsuper的理解。我們都知道:self是類的隱藏參數,指向當前調用方法的這個類的實例。那super呢?
很多人會想當然的認為superself類似,應該是指向父類的指針吧!”。這是很普遍的一個誤區。其實super是一個 Magic Keyword,它本質是一個編譯器標示符,和self 是指向的同一個消息接受者!他們兩個的不同點在于:super會告訴編譯器,調用class 這個方法時,要去父類的方法,而不是本類里的。
上面的例子不管調用[self class]還是[super class],接受消息的對象都是當前Son *xxx 這個對象。
當使用self調用方法時,會從當前類的方法列表中開始找,如果沒有,就從父類中再找;而當使用super時,則從父類的方法列表中開始找。然后調用父類的這個方法。

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

推薦閱讀更多精彩內容

  • 史上最全的iOS面試題及答案 iOS面試小貼士———————————————回答好下面的足夠了----------...
    Style_偉閱讀 2,371評論 0 35
  • 多線程、特別是NSOperation 和 GCD 的內部原理。運行時機制的原理和運用場景。SDWebImage的原...
    LZM輪回閱讀 2,020評論 0 12
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 1,995評論 0 7
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,182評論 30 470
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,775評論 18 139