iOS面試建議

定時(shí)器相關(guān)的問題

  • 定時(shí)器的模式問題是被問的最多的

UIScrollView(UITableView) 拖動(dòng)時(shí)執(zhí)行的是 UITrackingRunLoopMode,會(huì)導(dǎo)致暫停定時(shí)器,等恢復(fù)為 NSDefaultRunLoopMode 時(shí)才恢復(fù)定時(shí)器。
所以如果需要定時(shí)器在UIScrollView 拖動(dòng)時(shí)也不影響的話,建議添加到UITrackingRunLoopModeNSRunLoopCommonModes 中:

NSTimer *timer = [NSTimer timerWithTimeInterval:5 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode]; ///< 或者 NSRunLoopCommonModes
  • 自動(dòng)添加到當(dāng)前NSRunLoop的方式,這種方式會(huì)導(dǎo)致滑動(dòng)過(guò)程中定時(shí)器失效的問題,解決方式就是用(1)的方式設(shè)定NSRunLoop模式
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(test) userInfo:nil repeats:YES];
  • 定時(shí)器相關(guān)API的含義,沒用過(guò)的可能會(huì)誤解
[myTimer invalidate]; // 廢棄定時(shí)器 ,是永久的停止,移除定時(shí)器對(duì)象
[myTimer setFireDate:[NSDate distantFuture]]; // 關(guān)閉定時(shí)器;遙遠(yuǎn)的將來(lái)才能觸發(fā),功能相當(dāng)于關(guān)閉
[myTimer setFireDate:[NSDate distantPast]]; // 開啟定時(shí)器;很久很久以前就觸發(fā)了,功能相當(dāng)于開啟
  • GCD中的延時(shí)執(zhí)行,相當(dāng)于定時(shí)效果
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結(jié)合起來(lái)用,定時(shí)器是一種中斷源,知道這個(gè)的,基本上做得比較底層了,在實(shí)際工作中,還沒怎么遇到
@property (nonatomic ,strong)dispatch_source_t timer;//  注意:此處應(yīng)該使用強(qiáng)引用 strong
{
    //0.創(chuàng)建隊(duì)列
    dispatch_queue_t queue = dispatch_get_main_queue();
    //1.創(chuàng)建GCD中的定時(shí)器
    /*
     第一個(gè)參數(shù):創(chuàng)建source的類型 DISPATCH_SOURCE_TYPE_TIMER:定時(shí)器
     第二個(gè)參數(shù):0
     第三個(gè)參數(shù):0
     第四個(gè)參數(shù):隊(duì)列
     */
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

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

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

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

    //
    self.timer = timer;
}

此處注意一定要強(qiáng)引用定時(shí)器 ,否則定時(shí)器執(zhí)行到}后將會(huì)被釋放,無(wú)定時(shí)效果。
GCD定時(shí)器時(shí)間非常精準(zhǔn),最小的定時(shí)時(shí)間可以達(dá)到1納秒,所以用在非常精確的定時(shí)場(chǎng)合。

多線程相關(guān)問題

  • 串行隊(duì)列和并行隊(duì)列概念,同步執(zhí)行和異步執(zhí)行概念
NSLog(@"開始");
dispatch_sync(dispatch_get_main_queue(), ^{
    NSLog(@"進(jìn)行中");
});
NSLog(@"結(jié)束");

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

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

  • n個(gè)異步任務(wù)都執(zhí)行完畢后再執(zhí)行下一步的場(chǎng)景

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

通過(guò)dispatch_group_t來(lái)實(shí)現(xiàn),將每部分圖片下載請(qǐng)求放入到Group中,將合并圖片的操作放在dispatch_group_notify中實(shí)現(xiàn)。

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(), ^{
    // 合并圖片
});
  • 任務(wù)間依賴的場(chǎng)景

有3 個(gè)任務(wù):A: 從服務(wù)器上下載一張圖片,B:給這張圖片加個(gè)水印,C:把圖片返回給服務(wù)器。如何實(shí)現(xiàn)?

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

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

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

//4.設(shè)置依賴
[operation2 addDependency:operation1];      //任務(wù)二依賴任務(wù)一
[operation3 addDependency:operation2];      //任務(wù)三依賴任務(wù)二

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

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

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

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

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

(1)NSLock方式

   [xxxlock lock] //上鎖

  同步代碼塊

  [xxxlock unlock]//解鎖

(2)NSCondition方式

   [xxxCondition lock] //上鎖

  同步代碼塊

  [xxxCondition unlock]//解鎖

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

   @synchronized(self){

  線程執(zhí)行代碼;

  }

(4)OSSpinLock自旋鎖,atomic關(guān)鍵字,GCD串行隊(duì)列,循環(huán)鎖NSRecursiveLockpthreadmutex,信號(hào)量等等

本地存儲(chǔ),本地緩存

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

  • 數(shù)據(jù)持久化方案
    (1)plist屬性列表存儲(chǔ)(如NSUserDefaults
    (2)文件存儲(chǔ)(如二進(jìn)制數(shù)據(jù)寫入文件存儲(chǔ),通過(guò)NSFileManager來(lái)操作將下載起來(lái)的二進(jìn)制數(shù)據(jù)寫入文件中存儲(chǔ))
    (3)NSKeydeArchiver歸檔存儲(chǔ), === 這個(gè)要實(shí)現(xiàn)NSCoding協(xié)議,model要實(shí)現(xiàn)哪兩個(gè)函數(shù)?這點(diǎn)在實(shí)際使用中也可能忘記
    (4)數(shù)據(jù)庫(kù)SQLite3存儲(chǔ)(如FMDB、Core Data)=== 直接用SQL語(yǔ)句和CoreData的區(qū)別,CoreData的“坑”
    (5)KeyChain,用戶名密碼 === 代碼怎么實(shí)現(xiàn)?需要導(dǎo)入哪幾個(gè)系統(tǒng)framework?

  • SDWebImage的原理,或者其他圖片緩存庫(kù)
    (1)從內(nèi)存中(字典)找圖片(當(dāng)這個(gè)圖片在本次程序加載過(guò)),找到直接使用;
    (2)從沙盒中找,找到直接使用,緩存到內(nèi)存。
    (3)從網(wǎng)絡(luò)上獲取,使用,緩存到內(nèi)存,緩存到沙盒。

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

  • NSURLCache、NSURLRequest本身的緩存機(jī)制,AFNetworking用的是這一套。==== 這個(gè)用得不多,了解這些細(xì)節(jié)的不多,比較難

(1)獲得全局緩存對(duì)象(沒必要手動(dòng)創(chuàng)建)

NSURLCache *cache = [NSURLCache sharedURLCache]; 

(2)設(shè)置內(nèi)存緩存的最大容量(字節(jié)為單位,默認(rèn)為512KB)

- (void)setMemoryCapacity:(NSUInteger)memoryCapacity;

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

- (void)setDiskCapacity:(NSUInteger)diskCapacity;

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

(5)取得某個(gè)請(qǐng)求的緩存

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

(6)清除某個(gè)請(qǐng)求的緩存

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

(7)清除所有的緩存

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

NSURLRequestReloadIgnoringLocalCacheData // 忽略緩存,重新請(qǐng)求

NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未實(shí)現(xiàn)

NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 忽略緩存,重新請(qǐng)求

NSURLRequestReturnCacheDataElseLoad// 有緩存就用緩存,沒有緩存就重新請(qǐng)求

NSURLRequestReturnCacheDataDontLoad// 有緩存就用緩存,沒有緩存就不發(fā)請(qǐng)求,當(dāng)做請(qǐng)求出錯(cuò)處理(用于離線模式)

NSURLRequestReloadRevalidatingCacheData // 未實(shí)現(xiàn)

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

屬性修飾符

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

  • 打破引用循環(huán)的關(guān)鍵字? weak;會(huì)自動(dòng)設(shè)為nil,防止崩潰;如果能解釋清楚自動(dòng)設(shè)nil的原理,是高手

  • 默認(rèn)的關(guān)鍵字?strong

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

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

  • assign、weak、unsafe_unretained的區(qū)別? assign用于基礎(chǔ)類型,“如果用于對(duì)象,不會(huì)設(shè)為nil,會(huì)導(dǎo)致野指針,會(huì)帶來(lái)崩潰”

  • copy?NSString,NSArray,NSDictionary,NSSet等。引用計(jì)數(shù)對(duì)這些集合類型無(wú)意義

block引用循環(huán)

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

  • block不需要用weakSelf的場(chǎng)合?
    動(dòng)畫的時(shí)候不需要,比如

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

runtime動(dòng)態(tài)特性

  • NSString *obj = [[NSSData alloc]init] ,obj在編譯時(shí)和運(yùn)行時(shí)分別是什么類型的對(duì)象?
    編譯時(shí)是NSString, 運(yùn)行時(shí)是NSSData的一個(gè)實(shí)例
  1. 字典轉(zhuǎn)模型的原理?第三方庫(kù)?
    YYModel
    屬性列表,class_copyPropertyList

  2. 不埋點(diǎn)統(tǒng)計(jì),怎么做到? 熱更新JSPatch的原理?
    方法交換 Method Swizzling class_getInstanceMethod() method_exchangeImplementations()

  3. 如何給類別category添加屬性?
    關(guān)聯(lián)對(duì)象
    objc_setAssociatedObject objc_getAssociatedObject

  4. 如何在不創(chuàng)建類的前提下調(diào)用類的方法?用URL處理函數(shù)調(diào)用
    NSClassFromString()這個(gè)函數(shù)可以把URL中的字符串轉(zhuǎn)化為本地定義的類
    performSelector方法執(zhí)行相應(yīng)的方法

Native和H5的交互方式

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

第三方庫(kù)WebViewJavascriptBridge使用的是截取URL的方式,對(duì)UIWebViewWKWebView都適用

深復(fù)制,淺復(fù)制

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

iOS架構(gòu)

MVC
MVVM
MVP
VIPER

NSArray的實(shí)現(xiàn)方式?

指針的數(shù)組

需要區(qū)分流量來(lái)自哪個(gè)渠道,怎么做?

提升表格性能的方法?

(1)無(wú)用的網(wǎng)絡(luò)請(qǐng)求及時(shí)取消
(2)表格cell重用
(3)提前算好cell的高度
(4)圓角不要用cornerRadius

Https和Http的區(qū)別?

Https == http + socket + TLS
iOS9開始,XCode默認(rèn)用Https
如何繼續(xù)用Http?在plist中將某個(gè)字段打開
企業(yè)版賬號(hào)發(fā)布時(shí),ipa包可以http的,但是那個(gè)plist文件是需要https的,不然不能自動(dòng)安裝程序

bitCode

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

在ViewDidLoad中設(shè)置frame有什么問題?

UIImageView實(shí)現(xiàn)圓角的方法?

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

連接藍(lán)牙要注意些什么?

iOS中提供一個(gè)單例用于藍(lán)牙相關(guān)的函數(shù)
(1)廣播,用于掃描設(shè)備,選中特定設(shè)備
(2)建立點(diǎn)對(duì)點(diǎn)連接
(3)協(xié)議一般開頭是兼容微信的頭部,然后是自己的頭部,然后是數(shù)據(jù)
(4)數(shù)據(jù)要按照一定的大小進(jìn)行分包,每次傳輸?shù)拇笮∈鞘芟薜?br> (5)數(shù)據(jù)是NSData的,轉(zhuǎn)化為有意義的自定義類型時(shí)要注意大端和小端字節(jié)序的問題
(6)傳輸時(shí)有奇偶校驗(yàn)的事情,要跟firmware端的約定好
(7)丟包重傳,定時(shí)重連,空中升級(jí)等等都是比較令人頭疼的內(nèi)容

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 史上最全的iOS面試題及答案 iOS面試小貼士———————————————回答好下面的足夠了----------...
    Style_偉閱讀 2,578評(píng)論 0 35
  • 多線程、特別是NSOperation 和 GCD 的內(nèi)部原理。運(yùn)行時(shí)機(jī)制的原理和運(yùn)用場(chǎng)景。SDWebImage的原...
    LZM輪回閱讀 2,130評(píng)論 0 12
  • iOS面試小貼士 ———————————————回答好下面的足夠了------------------------...
    不言不愛閱讀 2,254評(píng)論 0 7
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,642評(píng)論 30 472
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,678評(píng)論 19 139

友情鏈接更多精彩內(nèi)容