準(zhǔn)備:
1.iOS的數(shù)據(jù)持久化方案
所有的本地持久化數(shù)據(jù)存儲的本質(zhì)都是寫文件,而且只能存到沙盒中。
沙盒機(jī)制是蘋果的一項(xiàng)安全機(jī)制,本質(zhì)就是系統(tǒng)給每個應(yīng)用分配了一個文件夾來存儲數(shù)據(jù),而且每個應(yīng)用只能訪問分配給自己的那個文件夾,其他應(yīng)用的文件夾是不能訪問的。
數(shù)據(jù)存儲的核心都是寫文件。主要有四種持久化方式:屬性列表,對象序列化,SQLite 數(shù)據(jù)庫, CoreData
2.常用的SQL語句
insert into values
delete from where
update set where
select from where
3.會哪些前端框架
Vue element-ui
4.Vue的特性
輕量級、雙向數(shù)據(jù)綁定、指令、組件化、客戶端路由、狀態(tài)管理
6.iOS系統(tǒng)架構(gòu)
從下到上:Core OS(核心操作系統(tǒng)層)、Core Services(核心服務(wù)層)、Media (媒體層)、Cocoa Touch(界面層)
5.block
block本質(zhì)上是一個OC對象,他內(nèi)部也有一個isa指針。block是封裝了函數(shù)調(diào)用以及函數(shù)調(diào)用環(huán)境的OC對象。
一共有三種block,分別是全局的、棧上的、堆上的。
6.手寫一個單例
- (LoginManager *)sharedLoginManager
{
if(!sharedLoginManager){
sharedLoginManager = [[self allocWithZone:Null]init];
}
return sharedLoginManager;
}
今天遇到的面試題:
1.傳值的回調(diào)方式有哪些,區(qū)別是什么?
答:
1.目標(biāo)動作對(Targe-Action):這里接受消息的對象是目標(biāo)(target),消息的選擇器(selector)是動作(action),一對一,向一個對象發(fā)送一個回調(diào)。
2.輔助對象:包括代理(Delegate)和數(shù)據(jù)源(DataSource),一對一,向一個對象發(fā)送多個回調(diào)。
3.通知(Notification),一對多,在程序中如果需要觸發(fā)多個(其他對象中)的回調(diào)對象時,可以使用通知的方式來完成。
4.Block:誰要傳值誰就定義含有參數(shù)的Block, 誰要調(diào)用誰就執(zhí)行這個Block,通過Block對象,可以將回調(diào)相關(guān)的代碼寫在同一個代碼段中。
總結(jié):這道題我只答出了后三種,忘記了第一種目標(biāo)動作對,他們的區(qū)別我只答出了delegate和Notification的區(qū)別是一對一和一對多,對于回調(diào)方式的區(qū)別沒有答出來。
2.block的屬性修飾用什么關(guān)鍵字,delegate的屬性修飾用什么關(guān)鍵字,為什么?assign和weak的區(qū)別?
答:block的屬性修飾詞是copy,默認(rèn)情況下block是存放在棧中,可能隨時被回收,通過copy操作可以使其在堆中保留一份,相當(dāng)于一直強(qiáng)引用著,因此如果block中用到self時需要將其進(jìn)行弱化,通過__weak或者_(dá)_unsafe_unretained。
delegate的屬性修飾關(guān)鍵詞是weak,是為了防止循環(huán)引用。
weak和assign的區(qū)別:
weak 只可以修飾對象。weak不會產(chǎn)生野指針的問題,因?yàn)閣eak修飾的對象被釋放后指針會自動置為nil,之后再向該對象發(fā)送消息也不會崩潰。weak是安全的。
assign 可修飾對象,和基本數(shù)據(jù)類型。如果修飾對象,會產(chǎn)生野指針問題;如果修飾基本數(shù)據(jù)類型則是安全的。修飾的對象釋放后,指針不會被自動置空,此時向?qū)ο蟀l(fā)送消息會崩潰。
總結(jié):這道題我只答出來了delegate的屬性修飾詞用weak,為了防止循環(huán)引用,block的屬性修飾詞答成了weak,weak是block中self的修飾詞,不是block的修飾詞。self用weak修飾也是因?yàn)閎lock 用了copy,為了弱化強(qiáng)引用,我沒有答出來主要是以前沒有深刻理解這一塊的內(nèi)容。還有關(guān)于使用weak不會產(chǎn)生野指針的問題,前兩天剛看過這個面試題,面試一問我又忘了,也是因?yàn)闆]有深刻理解,光死記硬背是不行的。
3.Category、擴(kuò)展、繼承的區(qū)別,有哪些應(yīng)用場景,往Category里可以添加屬性嗎?重寫一個類的方法用繼承好還是分類好?為什么?如果Category重寫父類的方法,執(zhí)行Category的方法后還會執(zhí)行父類中的方法嗎?項(xiàng)目中哪些地方用到了分類?
分類和擴(kuò)展的區(qū)別:
1.分類原則上只能添加方法(能添加屬性的的原因只是通過runtime解決無setter/getter的問題而已)
2.類擴(kuò)展不僅可以增加方法,還可以增加實(shí)例變量(或者屬性)
3.類擴(kuò)展中聲明的方法沒被實(shí)現(xiàn),編譯器會報(bào)警告,但是分類中的方法沒被實(shí)現(xiàn)編譯器是不會有任何警告的。這是因?yàn)轭悢U(kuò)展是在編譯階段被添加到類中,而分類是在運(yùn)行時添加到類中。
4.類擴(kuò)展不能像分類那樣擁有獨(dú)立的實(shí)現(xiàn)部分(@implementation部分),也就是說,類擴(kuò)展所聲明的方法必須依托對應(yīng)類的實(shí)現(xiàn)部分來實(shí)現(xiàn)。
5..m文件里的定義屬性,有時我們不會在.h里寫屬性,因?yàn)槟菢訒兂蓀ublic,只要import后,外部都可以訪問。如果我們只想當(dāng)前類用一下,只需要寫在.m里面,這樣的屬性或方法其實(shí)也是擴(kuò)展的一種。
分類與繼承的區(qū)別:
分類只能添加新的方法,不能刪除修改。
繼承可以增加、修改、刪除方法。并且可以增加屬性。
繼承可以修改父類的已經(jīng)存在方法,比如初始化方法init,重寫它之后你可以得到你想要的初始化對象,而分類則可以擴(kuò)展原有類的方法,比如你想讓UIImageView可以從網(wǎng)絡(luò)設(shè)置其image對象,則可以寫一個分類,擴(kuò)展這個原類中沒有的方法(或者說功能),因此看你的需求是什么,而不是籠統(tǒng)的說誰好誰壞。
Category重寫父類中的方法,會覆蓋父類方法,父類方法不會執(zhí)行。
繼承重寫一個方法,不會影響到其他地方正常使用這個方法。
項(xiàng)目中用到分類的地方:修改系統(tǒng)分類的樣式、功能,比如為NSDate新增分類,增加新的計(jì)時方法,為UIColor新增分類,增加新的顏色顯示方法。
總結(jié):這道題也是前兩天看過的面試題,結(jié)果面試時又把Category、擴(kuò)展、繼承三者說混了,后來我發(fā)現(xiàn)我的項(xiàng)目中用的都是Category,沒有用擴(kuò)展,因?yàn)橛昧藃untime的方法給Category添加屬性。這也使得我沒有真正理解分類和擴(kuò)展的區(qū)別。現(xiàn)在記住了他們的區(qū)別以后可以嘗試在項(xiàng)目中多用一些擴(kuò)展,而不是使用運(yùn)行時的方式。
4.閉環(huán)分享是做什么用的?
答:"閉環(huán)分享=分享出去+拉新回來"就是通過用戶的社交分享行為引導(dǎo)用戶下載App(對于未安裝App的用戶),或是在App內(nèi)觀看(對于已安裝此App的用戶),讓所有的用戶都能直達(dá)分享內(nèi)容所對應(yīng)的App頁面,成功把新用戶沉淀下去。
總結(jié):這個是我簡歷上寫的內(nèi)容,面試官問我這個功能是干什么用的,我答了分享之后再回到app,面試官問我分享完本來就可以回到app,是我描述的不夠準(zhǔn)確。應(yīng)該分為未安裝app和已安裝app的用戶分別說明,引導(dǎo)未安裝app的用戶下載app,已經(jīng)安裝app的用戶在app內(nèi)查看。這個是一年之前做的一個需求,要求分享app上的一個頁面到微信,微信上是h5頁面,要求點(diǎn)擊h5頁面上的按鈕可以跳回到app查看。當(dāng)初研究Universal Link的配置還花了很長時間,結(jié)果今天問我我什么都沒說出來,讓別人以為不是我做的一樣。
5.在Xib中一個ScrollView,如果內(nèi)容特別多應(yīng)該怎么設(shè)置約束?
答:在ScrollView中增加一個空白的View。
總結(jié):這個是面試官給的答案,面試官問我如果內(nèi)容特別多超出一屏怎么讓頁面滾動,我想不起來直接向她請教了。后來我看了一下我的項(xiàng)目中,我確實(shí)是這么做的,自己做過的東西就是想不起來,只能怪自己下的功夫還是不到位。
6.WKWebView和前端如何進(jìn)行交互,如何改變頁面的高度,如何設(shè)置頁面的背景色,用到的語句是什么,在哪個方法里調(diào)用?
WKWebView高度自適應(yīng)有三種方式:
1.通過KVO的方式
這種方式獲取的高度較為準(zhǔn)確,但要注意表格中多次回調(diào)高度的問題。
添加監(jiān)聽者
#pragma mark ------ < Private Method > ------
#pragma mark
- (void)addWebViewObserver {
[self.wkWebView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
}
監(jiān)聽高度變化
#pragma mark ------ < KVO > ------
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
/** < 法2 > */
/** < loading:防止?jié)L動一直刷新,出現(xiàn)閃屏 > */
if ([keyPath isEqualToString:@"contentSize"]) {
CGRect webFrame = self.wkWebView.frame;
webFrame.size.height = self.wkWebView.scrollView.contentSize.height;
self.wkWebView.frame = webFrame;
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:3 inSection:0], nil] withRowAnimation:UITableViewRowAnimationNone];
}
}
移除觀察者
- (void)removeWebViewObserver {
[self.wkWebView.scrollView removeObserver:self forKeyPath:@"contentSize"];
}
2.通過代理的方式
這種方法通過WKNavigationDelegate代理方法- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation,網(wǎng)頁加載完成通過JS獲取網(wǎng)頁內(nèi)容高度,但這種方式不一定就是最真實(shí)的高度,這時候可能網(wǎng)頁內(nèi)容還未加載完成,但以實(shí)際情況為準(zhǔn)。
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
CGFloat documentHeight = [result doubleValue];
CGRect webFrame = webView.frame;
webFrame.size.height = documentHeight;
webView.frame = webFrame;
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:3 inSection:0], nil] withRowAnimation:UITableViewRowAnimationNone];
}];
}
3.通過注入JS的方式,添加網(wǎng)頁加載完成回調(diào)獲取
第三種通常是接口返回HTMLString,然后自己在APP客戶端成網(wǎng)頁html、head、body這些標(biāo)簽,在合適的位置加入以下js代碼:
<script type=\"text/javascript\">
window.onload = function() {\
window.location.href = \"ready://\" + document.body.scrollHeight;\
}\
</script>
WKWebView背景色設(shè)置方法:
加載前直接給WKWebView.scrollview設(shè)背景色 加載完成方法里寫設(shè)置背景色的js交互方法:
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
[webView evaluateJavaScript:@"document.body.style.backgroundColor = \"#1E1E1E\"" completionHandler:nil];
}
總結(jié):這些方法的名字我都沒記住,開發(fā)時用的都是現(xiàn)成的方法,離開代碼就想不起來了,以后要鍛煉自己手寫代碼的能力。
7.幀動畫圖片占用內(nèi)存過大時如何解決?
答:1.創(chuàng)建圖片數(shù)組的時候用imageWithContentsOfFile而不是imageNamed方法。
imageNamed:加載到緩存中即使指向他的指針被銷毀了,內(nèi)存中依然會存在。好處是能快速加載該圖片,如果這個圖片經(jīng)常被用到建議此方法。
imageWithContentsOfFile:圖片是不會緩存的,如果指向他的指針被銷毀,內(nèi)存也會被釋放。這個方法適合不經(jīng)常使用,或者數(shù)量多的圖片。序列幀的圖片非常適合使用這個方法。
2.self.imageView.animationImages = nil;//這句話必須不能少,否則圖片會釋放不掉的
總結(jié):這道題我按照我平時項(xiàng)目中的做法答的,使用的是一個第三方框架,而面試官主要想知道的是如何解決幀動畫圖片占用內(nèi)存的問題,我的回答所答非所問了。
8.TableView嵌套NSTimer卡頓問題如何解決?
答:當(dāng)你拖動UItableView時,tableView的run loop處于UIEventTrackingRunLoopMode模式,在這種模式下,不處理定時器事件
因此將NSTimer所在的NSRunLoop修改mode為UITrackingRunLoopMode模式或NSRunLoopCommonModes
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
或
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
總結(jié):這道題我只回答了用runloop的方法解決,沒答出來具體的方法,這個例子在平時開發(fā)中也很常見,應(yīng)該把這幾個方法記住。
9.Vue傳值都有什么方法?
1.父組件向子組件傳值
2.子組件向父組件傳值
3.非父子組件傳值
引用官網(wǎng)一句話:父子組件的關(guān)系可以總結(jié)為 prop 向下傳遞,事件向上傳遞。父組件通過 prop 給子組件下發(fā)數(shù)據(jù),子組件通過事件給父組件發(fā)送消息。
總結(jié):今天問了我Vue的東西,因?yàn)槲业暮啔v上寫了,但是前端的面試題還沒看,也不會回答,還是先把iOS的面試題弄明白吧。
今日總結(jié):這兩天通過面試題學(xué)到了不少知識,收獲很大,找工作的同時也是深化基礎(chǔ)知識的機(jī)會,對以后開發(fā)很有幫助。我希望通過這一段時間的面試把iOS的基礎(chǔ)知識好好過一遍,邊找工作邊學(xué)習(xí),這兩天面試答的不是太好,不過面試機(jī)會還有很多,希望我每一天的面試都有進(jìn)步。