又到了不得不想換家公司的時(shí)間了。不是不想長(zhǎng)待,各種心酸就不排解了,下面是幾次面試的題目,次序不分先后。稍后會(huì)一一給自己解釋
1.線(xiàn)性表:順序表和鏈表優(yōu)缺點(diǎn),增刪改查插入如何操作,在內(nèi)存上是如何處理的;
2.表(UITableView)視圖的重用機(jī)制,如何實(shí)現(xiàn);
3.集合視圖(UICollectionView)瀑布流如何實(shí)現(xiàn)及優(yōu)化;
4.cell自適應(yīng)高度的處理方式及優(yōu)化;
5.loadView、awakeFromNib和layoutSubView、drawRect、setNeedsLayout、setNeedDisplay、layoutIfNeeded等方法何時(shí)調(diào)用;
6.如何使用cocoaPods管理第三方;
7.如何快速更換第三方類(lèi)庫(kù);
8.輪播圖的實(shí)現(xiàn)以三張圖片為例;
9.簡(jiǎn)述APNS,及遠(yuǎn)程和本地推送的實(shí)現(xiàn);
10.GCD的作用,適當(dāng)說(shuō)明使用過(guò)程;
11.簡(jiǎn)述HTTP協(xié)議錯(cuò)誤代碼的含義;
12.GET和POST的理解和區(qū)別;
13.熱修復(fù)的方式及如何實(shí)現(xiàn);
14.bug的搜集管理;
15.如何對(duì)接口數(shù)據(jù)進(jìn)行緩存;
16.簡(jiǎn)述SDWebImage的實(shí)現(xiàn)原理;
17.AF和SD是如何管理線(xiàn)程的,如何實(shí)現(xiàn)線(xiàn)程安全;
18.簡(jiǎn)述自己知道的加鎖方式;
19.簡(jiǎn)述幾大線(xiàn)程方式及區(qū)別;
20.對(duì)于常用動(dòng)畫(huà)你的理解和使用;
21.簡(jiǎn)述delegate和block,及block對(duì)于變量的修改問(wèn)題;
22.談?wù)勑阅軆?yōu)化;
23.instruments你用了哪些功能,如何檢測(cè)內(nèi)存泄露;
以上如此多的問(wèn)題,不論哪個(gè)都是一大塊的知識(shí),畢竟個(gè)人技能樹(shù)上沒(méi)點(diǎn)過(guò)的,還有很多,根本不敢談一個(gè)技能點(diǎn),被點(diǎn)滿(mǎn)的情況。還好面試一般都是需要簡(jiǎn)述即可,點(diǎn)到即止。
又想吐槽今年下半年的遭遇了,再次忠告自己或他人,珍視生命,遠(yuǎn)離自詡創(chuàng)業(yè)公司無(wú)休止無(wú)報(bào)酬無(wú)贊賞的公司。好了說(shuō)正題:
1.線(xiàn)性表:順序表和鏈表優(yōu)缺點(diǎn),增刪改查插入如何操作,在內(nèi)存上是如何處理的;
這個(gè)問(wèn)題是我近期的第一家面試公司問(wèn)的,因?yàn)槊嬖嚨哪切┨煲恢痹诠就ㄏ影啵緵](méi)有時(shí)間補(bǔ)充正規(guī)水軍的套路,回答的時(shí)候也是啃啃巴巴的,不過(guò)也算是回答到點(diǎn)上了。但是面試官預(yù)期的答案應(yīng)該是這樣的:
定義
1.線(xiàn)性表:零個(gè)或者多個(gè)數(shù)據(jù)元素的有限序列。
2.順序表和鏈表是線(xiàn)性表的兩種物理存儲(chǔ)方式,
3.順序表:用地址連續(xù)的存儲(chǔ)單元來(lái)存放數(shù)據(jù)元素的數(shù)據(jù)結(jié)構(gòu);
4.鏈表:鏈表是一種物理存儲(chǔ)單元上非連續(xù)、非順序的數(shù)據(jù)結(jié)構(gòu);
不同點(diǎn)
1.存儲(chǔ)空間上
順序表是物理地址連續(xù)的數(shù)據(jù)結(jié)構(gòu);
鏈表是一種物理地址非連續(xù)的數(shù)據(jù)結(jié)構(gòu)、
2.增刪改查上(時(shí)間上)
順序表:
正因?yàn)槲锢泶鎯?chǔ)結(jié)構(gòu)的不同,其表現(xiàn)形式不同,導(dǎo)致了其功能上的不同;
增:準(zhǔn)確說(shuō)是插入的一種,只是插入的位置是最后;
刪:若刪除位置后面還有元素,后邊元素全部前移一位;
插入:若所插入位置后有元素,后面元素分別后移一位;
查:獲取位置之后直接取;
改:查到之后,修改數(shù)據(jù)域數(shù)據(jù);
從功能實(shí)現(xiàn)看其優(yōu)缺點(diǎn):
順序表的存讀時(shí)間復(fù)雜度是O(1);
插入或者刪除的時(shí)候時(shí)間復(fù)雜度是O(n);
順序表優(yōu)點(diǎn):(主要用于查詢(xún))
(1)快速存取任意位置元素;
(2)無(wú)需為了表示元素之間邏輯關(guān)系而增加存儲(chǔ)空間(相對(duì)鏈表而言);
順序表缺點(diǎn):
增、刪、改操作
鏈表優(yōu)點(diǎn):(主要用于增刪該)
(1)增刪該時(shí)只需要修改指針;
(2)不需要事先明確表長(zhǎng);
鏈表缺點(diǎn):
查:鏈表的查詢(xún)需要從前向后掃描;
2.表(UITableView)視圖的重用機(jī)制,如何實(shí)現(xiàn);
reuseIdentifier
tableView創(chuàng)建的時(shí)候,會(huì)新建一個(gè)復(fù)用池保存著創(chuàng)建的cell,而cell的復(fù)用標(biāo)識(shí)符就是reuseIdentifier,不同標(biāo)識(shí)符的cell是不同類(lèi)的cell。通過(guò)dequeueReusableCellWithIdentifier:方法獲取cell。
重用--><對(duì)象池設(shè)計(jì)模式>
重用cell的創(chuàng)建有兩種方法:
初始化:沒(méi)有注冊(cè)的情況下,當(dāng)重用池取出的cell為空時(shí),需要初始化cell,并標(biāo)注其reuseIdentifier。
注冊(cè):
純代碼注冊(cè):代碼注冊(cè)
xib注冊(cè):代碼注冊(cè)
storyBoard注冊(cè):不需要代碼注冊(cè)
3.集合視圖(UICollectionView)瀑布流如何實(shí)現(xiàn)及優(yōu)化;
瀑布流實(shí)現(xiàn)的正確姿勢(shì)就是自定義UICollectionViewLayout,當(dāng)然自定義的時(shí)候需要實(shí)現(xiàn)以下內(nèi)部方法
1. - (CGSize)collectionViewContentSize;(主要返回cell的size)
2.- (void)prepareLayout;(預(yù)布局,每次刷新都會(huì)走的方法)
3.- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect;(獲取cell的布局屬性數(shù)組)
4.- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath;(根據(jù)indexPath設(shè)置cell布局屬性)
/**
* 初始化
*/
- (void)prepareLayout {
[super prepareLayout];
self.contentHeight = 0;
//清除以前計(jì)算的所有高度
[self.columnHeights removeAllObjects];
for (NSInteger i = 0; i < self.columnCount; i++) {
[self.columnHeights addObject:@(self.edgeInsets.top)];
}
//清除之前所有布局屬性
[self.attrsArray removeAllObjects];
//開(kāi)始創(chuàng)建每一個(gè)cell對(duì)應(yīng)發(fā)布局屬性
NSInteger count = [self.collectionView numberOfItemsInSection:0];
for (NSInteger i = 0; i < count; i++) {
//創(chuàng)建位置
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:i inSection:0];
//獲取indexPath位置cell對(duì)應(yīng)的布局屬性
UICollectionViewLayoutAttributes *attrs = [self layoutAttributesForItemAtIndexPath:indexPath];
[self.attrsArray addObject:attrs];
}
}
/**
* 決定cell的布局
*/
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
return self.attrsArray;
}
/**
* 返回indexPath位置cell對(duì)應(yīng)的布局屬性
*/
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
//創(chuàng)建布局屬性
UICollectionViewLayoutAttributes *attrs = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:indexPath];
//collectionView的寬度
CGFloat collectionViewW = self.collectionView.frame.size.width;
//設(shè)置布局屬性的frame
CGFloat w = (collectionViewW - self.edgeInsets.left - self.edgeInsets.right - (self.columnCount - 1) * self.columnMargin) / self.columnCount;
CGFloat h = [self.delegate waterflowlayout:self heightForItemAtIndex:indexPath.item itemWidth:w];
//找出高度最短的那一列
NSInteger destColumn = 0;
CGFloat minColumnHeight = [self.columnHeights[0] doubleValue];
for (NSInteger i = 0; i < self.columnCount; i++) {
//取得第i列的高度
CGFloat columnHeight = [self.columnHeights[i] doubleValue];
if (minColumnHeight > columnHeight) {
minColumnHeight = columnHeight;
destColumn = i;
}
}
CGFloat x = self.edgeInsets.left + destColumn * (w + self.columnMargin);
CGFloat y = minColumnHeight;
if (y != self.edgeInsets.top) {
y += self.rowMargin;
}
attrs.frame = CGRectMake(x, y, w, h);
//更新最短那列的高度
self.columnHeights[destColumn] = @(CGRectGetMaxY(attrs.frame));
//記錄內(nèi)容的高度
CGFloat columnHeight = [self.columnHeights[destColumn] doubleValue];
if (self.contentHeight < columnHeight) {
self.contentHeight = columnHeight;
}
return attrs;
}
- (CGSize)collectionViewContentSize {
return CGSizeMake(0, self.contentHeight + self.edgeInsets.bottom);
}
- (CGFloat)rowMargin {
if ([self.delegate respondsToSelector:@selector(rowMarginInWaterflowLayout:)]) {
return [self.delegate rowMarginInWaterflowLayout:self];
}else {
return SMDefaultRowMargin;
}
}
- (CGFloat)columnMargin {
if ([self.delegate respondsToSelector:@selector(columnMarginInWaterflowLayout:)]) {
return [self.delegate columnMarginInWaterflowLayout:self];
}else {
return SMDefaultColumnMargin;
}
}
- (NSInteger)columnCount {
if ([self.delegate respondsToSelector:@selector(columnCountInWaterflowLayout:)]) {
return [self.delegate columnCountInWaterflowLayout:self];
}else {
return SMDefaultColumnCount;
}
}
- (UIEdgeInsets)edgeInsets {
if ([self.delegate respondsToSelector:@selector(edgeInsetsInWaterflowLayout:)]) {
return [self.delegate edgeInsetsInWaterflowLayout:self];
}else {
return SMDefaultEdgeInsets;
}
}
優(yōu)化(tableView優(yōu)化參考)
1.通過(guò)正確的姿勢(shì)設(shè)置reuseIdentifier重用cell,headerView,footerView;
2.盡量減少不必要的透明View;
3.盡量避免漸變、拉伸、offScreen渲染;(maskToBouds)
4.一般情況下,處理數(shù)據(jù)的時(shí)候把對(duì)應(yīng)高度計(jì)算好,封進(jìn)Model中,避免重復(fù)計(jì)算;
5.展示網(wǎng)絡(luò)數(shù)數(shù)據(jù)時(shí),異步加載(一般都這樣干的)
6.如果設(shè)置shadow,使用shadowPath;
7.盡量減少subView,如果subView多變,考慮異步繪制或者重寫(xiě)drawRect;(drawRect慎用)
8.cellForRow中的邏輯如果需要處理數(shù)據(jù),請(qǐng)緩存結(jié)果;
9.對(duì)于數(shù)據(jù)結(jié)構(gòu)慎重對(duì)待,針對(duì)不同業(yè)務(wù)處理使用合適數(shù)據(jù)結(jié)構(gòu),避免性能消耗;(一般都這么干了)
10.對(duì)于不同的height,size,請(qǐng)perpare并且cache;
11.cell在使用代理,block,target-action等操作時(shí),防止循環(huán)引用;(weak,weak-Strong Dance,weak)
4.cell自適應(yīng)高度的處理方式及優(yōu)化;
我的處理方式是這樣的:cell自適應(yīng)是根據(jù)數(shù)據(jù)來(lái)的,那么在數(shù)據(jù)Model中建立對(duì)應(yīng)屬性并LazyLoad。
5.loadView、awakeFromNib和layoutSubView、drawRect、setNeedsLayout、setNeedDisplay、layoutIfNeeded等方法何時(shí)調(diào)用;
1.loadView()
調(diào)用順序:view->loadViewIfRequired->loadView
[super loadView];重載:加載指定xib--(否)-->加載同名xib--(否)-->創(chuàng)建空白View
當(dāng)重指向self.view的時(shí)候,可以在當(dāng)前方法中設(shè)置;
該方法只能重載不能主動(dòng)調(diào)用;
2. awakeFromNib()
方法由nib loading machinery 發(fā)出,當(dāng)調(diào)用loadNibFile時(shí),完成初始化設(shè)置和鏈接,并且在所有關(guān)聯(lián)的對(duì)象喚醒該方法。
當(dāng)一個(gè)視圖或者控制器加載多個(gè)nib文件時(shí),方法會(huì)被調(diào)用多次,所以當(dāng)重寫(xiě)該方法時(shí)需要注意;
3.layoutSubViews()
事件的調(diào)用時(shí)機(jī):
(1)addSubView:之后,并且子視圖有frame,
(2)在有子視圖的情況下,設(shè)置父視圖size;
(3)更新子視圖size時(shí),當(dāng)且僅當(dāng)size不同時(shí),才會(huì)調(diào)用子視圖的該方法;
(4)滾動(dòng)scrollView會(huì)觸發(fā)該方法;
(5)init的時(shí)候不會(huì)觸發(fā)該方法
4.drawRect()
(1)view的初始化沒(méi)有設(shè)置rect時(shí),方法不被調(diào)用。控制器中該方法調(diào)用在viewDidLoad之后;
(2)sizeToFit()之后會(huì)調(diào)用該方法;
(3)當(dāng)view屬性contentMode為UIViewContentModeRedraw。每次設(shè)置frame都會(huì)調(diào)用該方法;
(4)調(diào)用setNeedsDisplay,或者setNeedsDisplayInRect:時(shí),如果view的frame設(shè)置不為0,都會(huì)調(diào)用該方法;
注意:
(1)不可以顯示調(diào)用
(2)實(shí)時(shí)畫(huà)圖時(shí),不可用gestureRecognizer,只能用touchBegin等方法來(lái)調(diào)用setNeedsDisplay,實(shí)現(xiàn)調(diào)用drawRect;
5. setNeedsLayout
在receiver標(biāo)上一個(gè)需要被重新布局的標(biāo)記flag,在系統(tǒng)runloop的下一個(gè)周期自動(dòng)調(diào)用layoutSubviews;
6.setNeedDisplay
在receiver標(biāo)上一個(gè)需要被重新繪圖的標(biāo)記,在下一個(gè)draw周期自動(dòng)重繪,iphone device的刷新頻率是60hz,也就是1/60秒后重繪;
7.layoutIfNeeded
遍歷的不是superview鏈,應(yīng)該是subviews鏈;
如果,有需要刷新的標(biāo)記,立即調(diào)用layoutSubviews進(jìn)行布局(如果沒(méi)有標(biāo)記,不會(huì)調(diào)用layoutSubviews);
如果要立即刷新,要先調(diào)用[view setNeedsLayout],把標(biāo)記設(shè)為需要布局,然后馬上調(diào)用[view layoutIfNeeded],實(shí)現(xiàn)布局;
在視圖第一次顯示之前,標(biāo)記總是“需要刷新”的,可以直接調(diào)用[view layoutIfNeeded];
6.如何使用cocoaPods管理第三方;
要點(diǎn):
(1)cocoaPods的安裝;
(2)Podfile的創(chuàng)建、編輯、install;
7.如何快速更換第三方類(lèi)庫(kù);
簡(jiǎn)單來(lái)說(shuō)用第三方的正確姿勢(shì)必須要自己封裝下再使用,否則后期維護(hù)特別麻煩,修改的地方太多了。對(duì)于面試來(lái)說(shuō),直接提下封裝的優(yōu)點(diǎn),一般就可以了;
8.輪播圖的實(shí)現(xiàn)以三張圖片為例;
自己實(shí)現(xiàn):
這里給出思路:第一張圖片前加一張最后一張的圖片,目前有四張,在最后位置添加第二張圖片;可以在滾動(dòng)首尾的時(shí)候,減速方法中切換(視覺(jué)效果),保證正常輪播;
第三方:SDCycleScrollView
9.簡(jiǎn)述APNS,及遠(yuǎn)程和本地推送的實(shí)現(xiàn);
APNs全名是Apple Push Notification Service。
遠(yuǎn)程推送
1.deviceToken
該字段是在應(yīng)用注冊(cè)通知服務(wù)時(shí)APNS返回的設(shè)備唯一標(biāo)示。
2.遠(yuǎn)程推送流程
一般應(yīng)用在前臺(tái)時(shí)主要走應(yīng)用服務(wù)器和應(yīng)用的socket長(zhǎng)連接。這樣消息的傳遞要比APNS快,此時(shí)一般不需要deviceToken;應(yīng)用處于后臺(tái)時(shí),長(zhǎng)連接中斷,應(yīng)用服務(wù)器會(huì)將標(biāo)識(shí)信息和要發(fā)送的信息以一定模板發(fā)送給APNS,APNS將消息發(fā)送給具有標(biāo)識(shí)的用戶(hù);
3.本地推送
流程:創(chuàng)建本地通知、設(shè)置屬性、加入本地通知調(diào)度池、(iOS8.0以后)獲取授權(quán)。
10.GCD的作用,適當(dāng)說(shuō)明使用過(guò)程;
GCD主要用在后臺(tái)執(zhí)行較慢任務(wù);延遲執(zhí)行任務(wù);以及在后臺(tái)任務(wù)中,切換回主線(xiàn)程,更新UI;
對(duì)比:
pthread:通用于Unix/Linux/Windows的C語(yǔ)言線(xiàn)程管理API,可移植性強(qiáng),但是使用繁瑣,需要使用者管理線(xiàn)程生命周期;
NSThread:使用Objective-C實(shí)現(xiàn),輕量級(jí)的線(xiàn)程管理,但是也需要手動(dòng)管理線(xiàn)程的生命周期;
NSOperation:基于GCD,使用Objective-C實(shí)現(xiàn)的面向?qū)ο蟮木€(xiàn)程管理,比GCD更高級(jí),但是處理簡(jiǎn)單任務(wù)會(huì)比GCD代碼更多;
競(jìng)爭(zhēng)&同步:兩個(gè)線(xiàn)程搶奪同一個(gè)資源,就會(huì)競(jìng)爭(zhēng),為了防止競(jìng)爭(zhēng),一個(gè)線(xiàn)程擁有資源的時(shí)候,會(huì)對(duì)資源加鎖,另一個(gè)線(xiàn)程就要等待解鎖以后再擁有這個(gè)資源,這叫同步。
死鎖:兩個(gè)線(xiàn)程互相等待對(duì)方釋放資源;
主線(xiàn)程&后臺(tái)線(xiàn)程:主線(xiàn)程也叫前臺(tái)線(xiàn)程,程序啟動(dòng)的默認(rèn)線(xiàn)程,操作UI的線(xiàn)程。后臺(tái)線(xiàn)程,即非主線(xiàn)程,用于不影響主線(xiàn)程的完成一些任務(wù);
并行&串行:并行,就是幾個(gè)任務(wù)一起完成。串行,就是幾個(gè)任務(wù)一個(gè)接著一個(gè)完成。
同步&異步:同步執(zhí)行線(xiàn)程,等待新線(xiàn)程執(zhí)行完以后,再繼續(xù)執(zhí)行當(dāng)前線(xiàn)程,很少用到。異步執(zhí)行線(xiàn)程,在執(zhí)行新線(xiàn)程的同時(shí),繼續(xù)執(zhí)行當(dāng)前線(xiàn)程,常用。
11.簡(jiǎn)述HTTP協(xié)議錯(cuò)誤代碼的含義;
1xx(臨時(shí)響應(yīng))表示臨時(shí)響應(yīng)并需要請(qǐng)求者繼續(xù)執(zhí)行操作的狀態(tài)代碼。
100 (繼續(xù)) 請(qǐng)求者應(yīng)當(dāng)繼續(xù)提出請(qǐng)求。服務(wù)器返回此代碼表示已收到請(qǐng)求的第一部分,正在等待其余部分。
101 (切換協(xié)議) 請(qǐng)求者已要求服務(wù)器切換協(xié)議,服務(wù)器已確認(rèn)并準(zhǔn)備切換。
2xx(成功)表示成功處理了請(qǐng)求的狀態(tài)代碼。
200 (成功) 服務(wù)器已成功處理了請(qǐng)求。通常,這表示服務(wù)器提供了請(qǐng)求的網(wǎng)頁(yè)。
201 (已創(chuàng)建) 請(qǐng)求成功并且服務(wù)器創(chuàng)建了新的資源。
202 (已接受) 服務(wù)器已接受請(qǐng)求,但尚未處理。
203 (非授權(quán)信息) 服務(wù)器已成功處理了請(qǐng)求,但返回的信息可能來(lái)自另一來(lái)源。
204 (無(wú)內(nèi)容) 服務(wù)器成功處理了請(qǐng)求,但沒(méi)有返回任何內(nèi)容。
205 (重置內(nèi)容) 服務(wù)器成功處理了請(qǐng)求,但沒(méi)有返回任何內(nèi)容。
206 (部分內(nèi)容) 服務(wù)器成功處理了部分 GET 請(qǐng)求。
3xx(重定向)表示要完成請(qǐng)求,需要進(jìn)一步操作。 通常,這些狀態(tài)代碼用來(lái)重定向。
300 (多種選擇) 針對(duì)請(qǐng)求,服務(wù)器可執(zhí)行多種操作。服務(wù)器可根據(jù)請(qǐng)求者 (user agent) 選擇一項(xiàng)操作,或提供操作列表供請(qǐng)求者選擇。
301 (永久移動(dòng)) 請(qǐng)求的網(wǎng)頁(yè)已永久移動(dòng)到新位置。服務(wù)器返回此響應(yīng)(對(duì) GET 或 HEAD 請(qǐng)求的響應(yīng))時(shí),會(huì)自動(dòng)將請(qǐng)求者轉(zhuǎn)到新位置。
302 (臨時(shí)移動(dòng)) 服務(wù)器目前從不同位置的網(wǎng)頁(yè)響應(yīng)請(qǐng)求,但請(qǐng)求者應(yīng)繼續(xù)使用原有位置來(lái)進(jìn)行以后的請(qǐng)求。
303 (查看其他位置) 請(qǐng)求者應(yīng)當(dāng)對(duì)不同的位置使用單獨(dú)的 GET 請(qǐng)求來(lái)檢索響應(yīng)時(shí),服務(wù)器返回此代碼。
304 (未修改) 自從上次請(qǐng)求后,請(qǐng)求的網(wǎng)頁(yè)未修改過(guò)。服務(wù)器返回此響應(yīng)時(shí),不會(huì)返回網(wǎng)頁(yè)內(nèi)容。
305 (使用代理) 請(qǐng)求者只能使用代理訪(fǎng)問(wèn)請(qǐng)求的網(wǎng)頁(yè)。如果服務(wù)器返回此響應(yīng),還表示請(qǐng)求者應(yīng)使用代理。
307 (臨時(shí)重定向) 服務(wù)器目前從不同位置的網(wǎng)頁(yè)響應(yīng)請(qǐng)求,但請(qǐng)求者應(yīng)繼續(xù)使用原有位置來(lái)進(jìn)行以后的請(qǐng)求。
4xx(請(qǐng)求錯(cuò)誤)這些狀態(tài)代碼表示請(qǐng)求可能出錯(cuò),妨礙了服務(wù)器的處理。
400 (錯(cuò)誤請(qǐng)求) 服務(wù)器不理解請(qǐng)求的語(yǔ)法。
401 (未授權(quán)) 請(qǐng)求要求身份驗(yàn)證。 對(duì)于需要登錄的網(wǎng)頁(yè),服務(wù)器可能返回此響應(yīng)。
403 (禁止) 服務(wù)器拒絕請(qǐng)求。
404 (未找到) 服務(wù)器找不到請(qǐng)求的網(wǎng)頁(yè)。
405 (方法禁用) 禁用請(qǐng)求中指定的方法。
406 (不接受) 無(wú)法使用請(qǐng)求的內(nèi)容特性響應(yīng)請(qǐng)求的網(wǎng)頁(yè)。
407 (需要代理授權(quán)) 此狀態(tài)代碼與 401(未授權(quán))類(lèi)似,但指定請(qǐng)求者應(yīng)當(dāng)授權(quán)使用代理。
408 (請(qǐng)求超時(shí)) 服務(wù)器等候請(qǐng)求時(shí)發(fā)生超時(shí)。
409 (沖突) 服務(wù)器在完成請(qǐng)求時(shí)發(fā)生沖突。服務(wù)器必須在響應(yīng)中包含有關(guān)沖突的信息。
410 (已刪除) 如果請(qǐng)求的資源已永久刪除,服務(wù)器就會(huì)返回此響應(yīng)。
411 (需要有效長(zhǎng)度) 服務(wù)器不接受不含有效內(nèi)容長(zhǎng)度標(biāo)頭字段的請(qǐng)求。
412 (未滿(mǎn)足前提條件) 服務(wù)器未滿(mǎn)足請(qǐng)求者在請(qǐng)求中設(shè)置的其中一個(gè)前提條件。
413 (請(qǐng)求實(shí)體過(guò)大) 服務(wù)器無(wú)法處理請(qǐng)求,因?yàn)檎?qǐng)求實(shí)體過(guò)大,超出服務(wù)器的處理能力。
414 (請(qǐng)求的 URI 過(guò)長(zhǎng)) 請(qǐng)求的 URI(通常為網(wǎng)址)過(guò)長(zhǎng),服務(wù)器無(wú)法處理。
415 (不支持的媒體類(lèi)型) 請(qǐng)求的格式不受請(qǐng)求頁(yè)面的支持。
416 (請(qǐng)求范圍不符合要求) 如果頁(yè)面無(wú)法提供請(qǐng)求的范圍,則服務(wù)器會(huì)返回此狀態(tài)代碼。
417 (未滿(mǎn)足期望值) 服務(wù)器未滿(mǎn)足"期望"請(qǐng)求標(biāo)頭字段的要求。
5xx(服務(wù)器錯(cuò)誤)這些狀態(tài)代碼表示服務(wù)器在嘗試處理請(qǐng)求時(shí)發(fā)生內(nèi)部錯(cuò)誤。 這些錯(cuò)誤可能是服務(wù)器本身的錯(cuò)誤,而不是請(qǐng)求出錯(cuò)。
500 (服務(wù)器內(nèi)部錯(cuò)誤) 服務(wù)器遇到錯(cuò)誤,無(wú)法完成請(qǐng)求。
501 (尚未實(shí)施) 服務(wù)器不具備完成請(qǐng)求的功能。例如,服務(wù)器無(wú)法識(shí)別請(qǐng)求方法時(shí)可能會(huì)返回此代碼。
502 (錯(cuò)誤網(wǎng)關(guān)) 服務(wù)器作為網(wǎng)關(guān)或代理,從上游服務(wù)器收到無(wú)效響應(yīng)。
503 (服務(wù)不可用) 服務(wù)器目前無(wú)法使用(由于超載或停機(jī)維護(hù))。通常,這只是暫時(shí)狀態(tài)。
504 (網(wǎng)關(guān)超時(shí)) 服務(wù)器作為網(wǎng)關(guān)或代理,但是沒(méi)有及時(shí)從上游服務(wù)器收到請(qǐng)求。
505 (HTTP 版本不受支持) 服務(wù)器不支持請(qǐng)求中所用的 HTTP 協(xié)議版本。
12.GET和POST的理解和區(qū)別;
get請(qǐng)求和post請(qǐng)求都可以用于做獲取數(shù)據(jù)請(qǐng)求,在請(qǐng)求數(shù)據(jù)安全方面post請(qǐng)求比get請(qǐng)求安全;
get是以明文的方式向服務(wù)器發(fā)送請(qǐng)求,post是包裝到請(qǐng)求體body中后,在向服務(wù)器發(fā)送請(qǐng)求;
get請(qǐng)求的參數(shù)全部暴露在接口中,一般叫做明文請(qǐng)求或者傻瓜式請(qǐng)求,post請(qǐng)求的參數(shù)一般是以字典的方式進(jìn)行拼接,相對(duì)于get比較安全;
如果從服務(wù)器獲取數(shù)據(jù),或者查詢(xún)數(shù)據(jù),使用get請(qǐng)求;如果上傳數(shù)據(jù)到服務(wù)器或者修改服務(wù)器上傳數(shù)據(jù)使用post請(qǐng)求;
get請(qǐng)求的URL在使用過(guò)程中,會(huì)限制長(zhǎng)度,因此長(zhǎng)度非常長(zhǎng)的請(qǐng)求建議用post請(qǐng)求;
對(duì)文件大小的請(qǐng)求:get不允許向服務(wù)器上傳文件(圖片,pdf,音視頻);
13.熱修復(fù)的方式及如何實(shí)現(xiàn);
熱修復(fù)的相關(guān)框架還是很多的,簡(jiǎn)單來(lái)說(shuō)主要是利用了iOS運(yùn)行時(shí)特性。在運(yùn)行時(shí),調(diào)用修改的方法,達(dá)到熱更新的目的;
14.bug的搜集管理;
一般常用bug分析方式有:
1.使用友盟、百度等第三方崩潰統(tǒng)計(jì)工具。
2.自己實(shí)現(xiàn)應(yīng)用內(nèi)崩潰收集,并上傳服務(wù)器。
3.Xcode-Devices中直接查看某個(gè)設(shè)備的崩潰信息。
4.使用蘋(píng)果提供的Crash崩潰收集服務(wù)。
15.如何對(duì)接口數(shù)據(jù)進(jìn)行緩存;
輕量級(jí)<覆蓋型>
1.Plist文件<初始化文件路徑,數(shù)據(jù)寫(xiě)入路徑writeToFile:> 可以使用plist的數(shù)據(jù)類(lèi)型有 NSArray,NSDictionary,NSData,NSString,NSNumber,NSDate;
2.NSUserDefaults<存儲(chǔ)一些簡(jiǎn)單的信息>及時(shí)更新存儲(chǔ)synchronize;
3.NSKeyedArchiver<遵循NSCoping協(xié)議,歸檔解檔>
重量級(jí)<關(guān)系型>
1.sqlite3<FMDB>直接編寫(xiě)splite3語(yǔ)言
2.coreData<遷徙>對(duì)于數(shù)據(jù)庫(kù)的封裝,圖形化設(shè)計(jì),提供了一種映射的存儲(chǔ)關(guān)系;
16.簡(jiǎn)述SDWebImage的實(shí)現(xiàn)原理;
(1)入口 sd_setImageWithURL: placeholderImage: options: progress: completed:會(huì)先把 placeholderImage 顯示,然后會(huì)把重復(fù)的請(qǐng)求刪除掉, SDWebImageManager 根據(jù) URL 開(kāi)始處理圖片,處理進(jìn)度progress,處理完成complete;
(2)進(jìn)入 SDWebImageManager-downloadWithURL:delegate:options:userInfo: 交給 SDImageCache 從緩存查找圖片是否已經(jīng)下載queryDiskCacheForKey:delegate:userInfo:;
(3)先從內(nèi)存圖片緩存查找是否有圖片,如果內(nèi)存中已經(jīng)有圖片緩存, SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager;
(4)SDWebImageManagerDelegate 回調(diào) webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示圖片;
(5)如果內(nèi)存緩存中沒(méi)有,生成 NSInvocationOperation 添加到隊(duì)列開(kāi)始從硬盤(pán)查找圖片是否已經(jīng)緩存;
(6)根據(jù) URLKey 在硬盤(pán)緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進(jìn)行的操作,所以回主線(xiàn)程進(jìn)行結(jié)果回調(diào) notifyDelegate:;
(7)如果上一操作從硬盤(pán)讀取到了圖片,將圖片添加到內(nèi)存緩存中(如果空閑內(nèi)存過(guò)小,會(huì)先清空內(nèi)存緩存)。SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo:。進(jìn)而回調(diào)展示圖片;
(8)如果從硬盤(pán)緩存目錄讀取不到圖片,說(shuō)明所有緩存都不存在該圖片,需要下載圖片,回調(diào) imageCache:didNotFindImageForKey:userInfo:;
(9)共享或重新生成一個(gè)下載器 SDWebImageDownloader 開(kāi)始下載圖片;
(10)圖片下載由 NSURLConnection 來(lái)做,實(shí)現(xiàn)相關(guān) delegate 來(lái)判斷圖片下載中、下載完成和下載失敗;
(11)connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進(jìn)度加載效果;
(12)connectionDidFinishLoading: 數(shù)據(jù)下載完成后交給 SDWebImageDecoder 做圖片解碼處理;
(13)圖片解碼處理在一個(gè) NSOperationQueue 完成,不會(huì)拖慢主線(xiàn)程 UI。如果有需要對(duì)下載的圖片進(jìn)行二次處理,最好也在這里完成,效率會(huì)好很多;
(14)在主線(xiàn)程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo: 回調(diào)給 SDWebImageDownloader;
(15)imageDownloader:didFinishWithImage: 回調(diào)給 SDWebImageManager 告知圖片下載完成;
(16)通知所有的 downloadDelegates 下載完成,回調(diào)給需要的地方展示圖片;
(17)將圖片保存到 SDImageCache 中,內(nèi)存緩存和硬盤(pán)緩存同時(shí)保存。寫(xiě)文件到硬盤(pán)也在以單獨(dú) NSInvocationOperation 完成,避免拖慢主線(xiàn)程;
(18)SDImageCache 在初始化的時(shí)候會(huì)注冊(cè)一些消息通知,在內(nèi)存警告或退到后臺(tái)的時(shí)候清理內(nèi)存圖片緩存,應(yīng)用結(jié)束的時(shí)候清理過(guò)期圖片;
(19)SDWebImage 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用;
(20)SDWebImagePrefetcher 可以預(yù)先下載圖片,方便后續(xù)使用。
17.AF和SD是如何管理線(xiàn)程的,如何實(shí)現(xiàn)線(xiàn)程安全;
1.AF并沒(méi)有為每個(gè)請(qǐng)求創(chuàng)建一個(gè)線(xiàn)程,而是將每個(gè)請(qǐng)求封裝成一個(gè)NSOperation放到queue中,當(dāng)operation執(zhí)行時(shí),都會(huì)在一個(gè)單獨(dú)線(xiàn)程中創(chuàng)建NSURLSession對(duì)象,并用KVO監(jiān)聽(tīng)所有回調(diào)。下面是值得借鑒的地方
(1)并發(fā)粒度:因?yàn)锳F的所有網(wǎng)絡(luò)請(qǐng)求都在operationQueue中,而該queue會(huì)有多個(gè)并發(fā)線(xiàn)程來(lái)執(zhí)行,最大的并發(fā)線(xiàn)程數(shù)一般是系統(tǒng)根據(jù)硬件信息默認(rèn)的,AF則留有設(shè)置最大并發(fā)線(xiàn)程數(shù)的接口;
(2)block優(yōu)化:如果某一個(gè)operation的success和failure的回調(diào)占用較多CPU,則可以創(chuàng)建一個(gè)任務(wù)隊(duì)列并賦值給該operation的completionQueue;
2.SDWebImage中每個(gè)圖片的下載都是一個(gè)Operation操作,每個(gè)operation在單獨(dú)線(xiàn)程中創(chuàng)建自己的NSURLSession對(duì)象,并通過(guò)觀(guān)察者模式,發(fā)送加載狀態(tài)的廣播,以便對(duì)加載進(jìn)行管控。
18.簡(jiǎn)述自己知道的加鎖方式;
1. @synchronized 關(guān)鍵字加鎖(最耗時(shí))
2. NSLock 對(duì)象鎖
3. NSCondition
4. NSConditionLock 條件鎖(最耗時(shí))
5. NSRecursiveLock 遞歸鎖
6. pthread_mutex 互斥鎖(C語(yǔ)言)
7. dispatch_semaphore 信號(hào)量實(shí)現(xiàn)加鎖(GCD)(加鎖時(shí)間第二快)
8. OSSpinLock(已不再安全)(加鎖時(shí)間最快)
19.簡(jiǎn)述幾大線(xiàn)程方式及區(qū)別;
1.pthread:跨平臺(tái)可移植,線(xiàn)程需手動(dòng)管理;
2.NSThread:面向?qū)ο螅苯硬僮骶€(xiàn)程對(duì)象,需要手動(dòng)管理線(xiàn)程生命周期,可以獲取當(dāng)前線(xiàn)程及是否為主線(xiàn)程;
3.GCD:充分利用設(shè)備多核,線(xiàn)程生命周期自動(dòng)管理,使用之后不用管什么時(shí)候結(jié)束。
4.NSOperation:封裝GCD,更加面向?qū)ο螅€(xiàn)程生命周期手動(dòng)管理。相對(duì)GCD可以實(shí)現(xiàn)更高級(jí)的管理功能。
20.對(duì)于常用動(dòng)畫(huà)你的理解和使用;
1.UIView動(dòng)畫(huà)
通過(guò)UIView支持的動(dòng)畫(huà)屬性來(lái)實(shí)現(xiàn)動(dòng)畫(huà)效果,如frame,bounds,center,tranform,alpha,backgroundColor,contentStretch等,對(duì)于約束的修改則需要在block中調(diào)用 setNeedsLayout,而約束的改變?cè)趧?dòng)畫(huà)之后執(zhí)行。
2.核心動(dòng)畫(huà)
核心動(dòng)畫(huà)采用Core Animation框架,直接作用在CALayer層,而不再UIView;
UIView與CALayer的主要區(qū)別
1、UIView是可以響應(yīng)事件的,但是CALayer不能響應(yīng)事件
2、UIView主要負(fù)責(zé)管理顯示內(nèi)容,而CALayer主要負(fù)責(zé)渲染和呈現(xiàn)。如果沒(méi)有CALayer,我們是看不到內(nèi)容的。
3、CALayer內(nèi)部維護(hù)著三分layer tree,分別是presentLayer tree(動(dòng)畫(huà)樹(shù)),modeLayer tree(模型樹(shù)),render tree(渲染樹(shù)),在做iOS動(dòng)畫(huà)的時(shí)候,我們修改動(dòng)畫(huà)的屬性,在動(dòng)畫(huà)的其實(shí)是CALayer的present Layer的屬性值,而最終展示在界面上的其實(shí)是提供UIView的modelLayer。
CALayer核心動(dòng)畫(huà)與UIView動(dòng)畫(huà)的區(qū)別:
UIView封裝的動(dòng)畫(huà)執(zhí)行完畢之后不會(huì)反彈,CALayer核心動(dòng)畫(huà)則會(huì);另外UIView的動(dòng)畫(huà)期間可以處理用戶(hù)事件,CALayer核心動(dòng)畫(huà)則不能。例如:如果是通過(guò)CALayer核心動(dòng)畫(huà)改變layer的位置狀態(tài),表面上看雖然已經(jīng)改變了,但是實(shí)際上它的位置是沒(méi)有改變的。
21.簡(jiǎn)述delegate和block,及block對(duì)于變量的修改問(wèn)題;
delegate和block主要解決對(duì)象之間通信問(wèn)題。都需要注意循環(huán)引用的問(wèn)題,ARC下,delegate為weak修飾,block用copy修飾,防止block實(shí)現(xiàn)代碼被釋放掉。在block塊內(nèi)對(duì)外局部變量修改時(shí),局部變量需要__block修飾。
22.談?wù)勑阅軆?yōu)化;
1.性能優(yōu)化:
(1)UITableView優(yōu)化
(2)網(wǎng)絡(luò)請(qǐng)求優(yōu)化
(3)圖片加載優(yōu)化
2.代碼優(yōu)化:
(1)合理使用設(shè)計(jì)模式
(2)善于使用面向?qū)ο笳Z(yǔ)言特性
(3)設(shè)計(jì)優(yōu)化,緩存等
(4)代碼規(guī)范
3.程序體積優(yōu)化:
4.數(shù)據(jù)安全:
23.instruments你用了哪些功能,如何檢測(cè)內(nèi)存泄露;
1. Zombies:查看僵尸對(duì)象
2.Leaks:內(nèi)存泄漏
3.Time Profiler:查看加載耗時(shí)