又到了不得不想換家公司的時(shí)間了五督。不是不想長(zhǎng)待,各種心酸就不排解了蛔翅,下面是幾次面試的題目敲茄,次序不分先后。稍后會(huì)一一給自己解釋
1.線性表:順序表和鏈表優(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.如何快速更換第三方類庫(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是如何管理線程的棠众,如何實(shí)現(xiàn)線程安全;
18.簡(jiǎn)述自己知道的加鎖方式有决;
19.簡(jiǎn)述幾大線程方式及區(qū)別闸拿;
20.對(duì)于常用動(dòng)畫你的理解和使用;
21.簡(jiǎn)述delegate和block书幕,及block對(duì)于變量的修改問(wèn)題新荤;
22.談?wù)勑阅軆?yōu)化;
23.instruments你用了哪些功能台汇,如何檢測(cè)內(nèi)存泄露苛骨;
以上如此多的問(wèn)題,不論哪個(gè)都是一大塊的知識(shí)励七,畢竟個(gè)人技能樹上沒(méi)點(diǎn)過(guò)的智袭,還有很多,根本不敢談一個(gè)技能點(diǎn)掠抬,被點(diǎn)滿的情況吼野。還好面試一般都是需要簡(jiǎn)述即可,點(diǎn)到即止两波。
又想吐槽今年下半年的遭遇了瞳步,再次忠告自己或他人闷哆,珍視生命,遠(yuǎn)離自詡創(chuàng)業(yè)公司無(wú)休止無(wú)報(bào)酬無(wú)贊賞的公司单起。好了說(shuō)正題:
1.線性表:順序表和鏈表優(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.線性表:零個(gè)或者多個(gè)數(shù)據(jù)元素的有限序列碳胳。
2.順序表和鏈表是線性表的兩種物理存儲(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):(主要用于查詢)
(1)快速存取任意位置元素;
(2)無(wú)需為了表示元素之間邏輯關(guān)系而增加存儲(chǔ)空間(相對(duì)鏈表而言);
順序表缺點(diǎn):
增糠馆、刪嘶伟、改操作
鏈表優(yōu)點(diǎn):(主要用于增刪該)
(1)增刪該時(shí)只需要修改指針;
(2)不需要事先明確表長(zhǎng)又碌;
鏈表缺點(diǎ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是不同類的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];
//開始創(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多變作煌,考慮異步繪制或者重寫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)重寫該方法時(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í)畫圖時(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.如何快速更換第三方類庫(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í)的用戶骏全;
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ù)中母怜,切換回主線程,更新UI缚柏;
對(duì)比:
pthread:通用于Unix/Linux/Windows的C語(yǔ)言線程管理API苹熏,可移植性強(qiáng),但是使用繁瑣币喧,需要使用者管理線程生命周期轨域;
NSThread:使用Objective-C實(shí)現(xiàn),輕量級(jí)的線程管理杀餐,但是也需要手動(dòng)管理線程的生命周期疙挺;
NSOperation:基于GCD,使用Objective-C實(shí)現(xiàn)的面向?qū)ο蟮木€程管理怜浅,比GCD更高級(jí),但是處理簡(jiǎn)單任務(wù)會(huì)比GCD代碼更多;
競(jìng)爭(zhēng)&同步:兩個(gè)線程搶奪同一個(gè)資源恶座,就會(huì)競(jìng)爭(zhēng)搀暑,為了防止競(jìng)爭(zhēng),一個(gè)線程擁有資源的時(shí)候跨琳,會(huì)對(duì)資源加鎖自点,另一個(gè)線程就要等待解鎖以后再擁有這個(gè)資源,這叫同步脉让。
死鎖:兩個(gè)線程互相等待對(duì)方釋放資源桂敛;
主線程&后臺(tái)線程:主線程也叫前臺(tái)線程,程序啟動(dòng)的默認(rèn)線程溅潜,操作UI的線程术唬。后臺(tái)線程,即非主線程滚澜,用于不影響主線程的完成一些任務(wù)粗仓;
并行&串行:并行,就是幾個(gè)任務(wù)一起完成设捐。串行借浊,就是幾個(gè)任務(wù)一個(gè)接著一個(gè)完成。
同步&異步:同步執(zhí)行線程萝招,等待新線程執(zhí)行完以后蚂斤,再繼續(xù)執(zhí)行當(dāng)前線程,很少用到槐沼。異步執(zhí)行線程曙蒸,在執(zhí)行新線程的同時(shí),繼續(xù)執(zhí)行當(dāng)前線程母赵,常用逸爵。
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)求者只能使用代理訪問(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))類似兑徘,但指定請(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 (未滿足前提條件) 服務(wù)器未滿足請(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 (不支持的媒體類型) 請(qǐng)求的格式不受請(qǐng)求頁(yè)面的支持虑粥。
416 (請(qǐng)求范圍不符合要求) 如果頁(yè)面無(wú)法提供請(qǐng)求的范圍,則服務(wù)器會(huì)返回此狀態(tài)代碼宪哩。
417 (未滿足期望值) 服務(wù)器未滿足"期望"請(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ù)贩汉,或者查詢數(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.使用蘋果提供的Crash崩潰收集服務(wù)蚯窥。
15.如何對(duì)接口數(shù)據(jù)進(jìn)行緩存掸鹅;
輕量級(jí)<覆蓋型>
1.Plist文件<初始化文件路徑,數(shù)據(jù)寫入路徑writeToFile:> 可以使用plist的數(shù)據(jù)類型有 NSArray,NSDictionary,NSData,NSString,NSNumber,NSDate拦赠;
2.NSUserDefaults<存儲(chǔ)一些簡(jiǎn)單的信息>及時(shí)更新存儲(chǔ)synchronize巍沙;
3.NSKeyedArchiver<遵循NSCoping協(xié)議,歸檔解檔>
重量級(jí)<關(guān)系型>
1.sqlite3<FMDB>直接編寫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 開始處理圖片,處理進(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ì)列開始從硬盤查找圖片是否已經(jīng)緩存;
(6)根據(jù) URLKey 在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進(jìn)行的操作援岩,所以回主線程進(jìn)行結(jié)果回調(diào) notifyDelegate:;
(7)如果上一操作從硬盤讀取到了圖片熟史,將圖片添加到內(nèi)存緩存中(如果空閑內(nèi)存過(guò)小,會(huì)先清空內(nèi)存緩存)窄俏。SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo:。進(jìn)而回調(diào)展示圖片;
(8)如果從硬盤緩存目錄讀取不到圖片碘菜,說(shuō)明所有緩存都不存在該圖片凹蜈,需要下載圖片,回調(diào) imageCache:didNotFindImageForKey:userInfo:;
(9)共享或重新生成一個(gè)下載器 SDWebImageDownloader 開始下載圖片;
(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ì)拖慢主線程 UI计雌。如果有需要對(duì)下載的圖片進(jìn)行二次處理悄晃,最好也在這里完成,效率會(huì)好很多;
(14)在主線程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成凿滤,imageDecoder:didFinishDecodingImage:userInfo: 回調(diào)給 SDWebImageDownloader;
(15)imageDownloader:didFinishWithImage: 回調(diào)給 SDWebImageManager 告知圖片下載完成;
(16)通知所有的 downloadDelegates 下載完成妈橄,回調(diào)給需要的地方展示圖片;
(17)將圖片保存到 SDImageCache 中,內(nèi)存緩存和硬盤緩存同時(shí)保存翁脆。寫文件到硬盤也在以單獨(dú) NSInvocationOperation 完成眷蚓,避免拖慢主線程;
(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是如何管理線程的篙贸,如何實(shí)現(xiàn)線程安全;
1.AF并沒(méi)有為每個(gè)請(qǐng)求創(chuàng)建一個(gè)線程枫疆,而是將每個(gè)請(qǐng)求封裝成一個(gè)NSOperation放到queue中爵川,當(dāng)operation執(zhí)行時(shí),都會(huì)在一個(gè)單獨(dú)線程中創(chuàng)建NSURLSession對(duì)象养铸,并用KVO監(jiān)聽所有回調(diào)雁芙。下面是值得借鑒的地方
(1)并發(fā)粒度:因?yàn)锳F的所有網(wǎng)絡(luò)請(qǐng)求都在operationQueue中轧膘,而該queue會(huì)有多個(gè)并發(fā)線程來(lái)執(zhí)行,最大的并發(fā)線程數(shù)一般是系統(tǒng)根據(jù)硬件信息默認(rèn)的兔甘,AF則留有設(shè)置最大并發(fā)線程數(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ú)線程中創(chuàng)建自己的NSURLSession對(duì)象,并通過(guò)觀察者模式澡匪,發(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)述幾大線程方式及區(qū)別疑苔;
1.pthread:跨平臺(tái)可移植,線程需手動(dòng)管理甸鸟;
2.NSThread:面向?qū)ο蟮敕眩苯硬僮骶€程對(duì)象,需要手動(dòng)管理線程生命周期抢韭,可以獲取當(dāng)前線程及是否為主線程薪贫;
3.GCD:充分利用設(shè)備多核,線程生命周期自動(dòng)管理刻恭,使用之后不用管什么時(shí)候結(jié)束瞧省。
4.NSOperation:封裝GCD,更加面向?qū)ο篦⒓郑€程生命周期手動(dòng)管理鞍匾。相對(duì)GCD可以實(shí)現(xiàn)更高級(jí)的管理功能。
20.對(duì)于常用動(dòng)畫你的理解和使用骑科;
1.UIView動(dòng)畫
通過(guò)UIView支持的動(dòng)畫屬性來(lái)實(shí)現(xiàn)動(dòng)畫效果候学,如frame,bounds纵散,center梳码,tranform,alpha伍掀,backgroundColor掰茶,contentStretch等,對(duì)于約束的修改則需要在block中調(diào)用 setNeedsLayout蜜笤,而約束的改變?cè)趧?dòng)畫之后執(zhí)行濒蒋。
2.核心動(dòng)畫
核心動(dòng)畫采用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)畫樹)贮配,modeLayer tree(模型樹),render tree(渲染樹)塞赂,在做iOS動(dòng)畫的時(shí)候泪勒,我們修改動(dòng)畫的屬性,在動(dòng)畫的其實(shí)是CALayer的present Layer的屬性值宴猾,而最終展示在界面上的其實(shí)是提供UIView的modelLayer酣藻。
CALayer核心動(dòng)畫與UIView動(dòng)畫的區(qū)別:
UIView封裝的動(dòng)畫執(zhí)行完畢之后不會(huì)反彈,CALayer核心動(dòng)畫則會(huì)鳍置;另外UIView的動(dòng)畫期間可以處理用戶事件,CALayer核心動(dòng)畫則不能送淆。例如:如果是通過(guò)CALayer核心動(dòng)畫改變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í)