定時(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í)也不影響的話,建議添加到UITrackingRunLoopMode或 NSRunLoopCommonModes 中:
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)鎖NSRecursiveLock,pthread的mutex,信號(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)鍵字?
strongnonatomic? 非線程安全,加快速度。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就變成了nilblock不需要用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í)例
字典轉(zhuǎn)模型的原理?第三方庫(kù)?
YYModel
屬性列表,class_copyPropertyList不埋點(diǎn)統(tǒng)計(jì),怎么做到? 熱更新
JSPatch的原理?
方法交換Method Swizzling class_getInstanceMethod() method_exchangeImplementations()如何給類別
category添加屬性?
關(guān)聯(lián)對(duì)象
objc_setAssociatedObject objc_getAssociatedObject如何在不創(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ì)UIWebView和WKWebView都適用
深復(fù)制,淺復(fù)制
NSArray *array = @[@"a", @"b", @"c", @"d"];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
-
copyArray與array的地址是否一樣? 一樣 -
mCopyArray和array的地址又是否一樣? 不一樣 - 改變
mCopyArray里面的元素內(nèi)容,是否會(huì)刻變array的內(nèi)容? 不改變 -
copy和mutableCopy的拷貝操作有何不同?
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)layer的CornerRadius
(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ì)self和super的理解。我們都知道:self是類的隱藏參數(shù),指向當(dāng)前調(diào)用方法的這個(gè)類的實(shí)例。那super呢?
很多人會(huì)想當(dāng)然的認(rèn)為super和self類似,應(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è)方法。