原文地址:https://blog.csdn.net/wzc10101415/article/details/51840123
1累驮、KVC的底層實現(xiàn)?
當(dāng)一個對象調(diào)用setValue方法時拦焚,方法內(nèi)部會做以下操作:
①檢查是否存在相應(yīng)key的set方法,如果存在旧困,就調(diào)用set方法
②如果set方法不存在,就會查找與key相同名稱并且?guī)聞澗€的成員屬性,如果有,則直接給成員屬性賦值
③如果沒有找到_key,就會查找相同名稱的屬性key抢野,如果有就直接賦值
④如果還沒找到,則調(diào)用valueForUndefinedKey:和setValue:forUndefinedKey:方法各墨。
這些方法的默認(rèn)實現(xiàn)都是拋出異常指孤,我們可以根據(jù)需要重寫它們。
2、__block和__weak修飾符的區(qū)別恃轩?
1.__block不管是ARC還是MRC模式下都可以使用结洼,可以修飾對象,還可以修飾基本數(shù)據(jù)類型叉跛。
2.__weak只能在ARC模式下使用松忍,也只能修飾對象(NSString),不能修飾基本數(shù)據(jù)類型(int)筷厘。
3.__block對象可以在block中被重新賦值鸣峭,__weak不可以。
3敞掘、block和代理的區(qū)別叽掘,哪個更好?
1 代理回調(diào)更面向過程玖雁,block更面向結(jié)果更扁。
2.如果需要在執(zhí)行的不同步驟時被通知,你就要使用代理赫冬。
3.如果只需要請求的消息或者失敗的詳情浓镜,應(yīng)該使用block。
4.block更適合與狀態(tài)無關(guān)的操作劲厌,比如被告知某些結(jié)果膛薛,block之間是不會相互影響的。
5.但是代理更像一個生產(chǎn)流水線补鼻,每個回調(diào)方法是生產(chǎn)線上的一個處理步驟哄啄,一個回調(diào)的變動可能會引起另一個回調(diào)的變動。
6.要是一個對象有超過一個的不同事件风范,應(yīng)該使用代理咨跌。
7.一個對象只有一個代理,要是某個對象是個單例對象硼婿,就不能使用代理锌半。
8.要是一個對象調(diào)用方法需要返回一些額外的信息,就可能需要使用代理寇漫。
4刊殉、Object C中創(chuàng)建線程的方法是什么?如果在主線程中執(zhí)行代碼,方法是什么?如果想延時執(zhí)行代碼州胳、方法又是什么?
線程創(chuàng)建有三種方法:使用NSThread創(chuàng)建记焊、使用GCD的dispatch、使用子類化的NSOperation,然后將其加入NSOperationQueue;
NSThread創(chuàng)建線程的三種方法:
NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"nil"];
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"我是分離出來的子線程"];
[self performSelectorInBackground:@selector(run:) withObject:@"我是后臺線程"];
在主線程執(zhí)行代碼栓撞,就調(diào)用performSelectorOnMainThread方法亚亲。
如果想延時執(zhí)行代碼可以調(diào)用performSelector:onThread:withObject:waitUntilDone:方法;
GCD:
利用異步函數(shù)dispatch_async()創(chuàng)建子線程。
在主線程執(zhí)行代碼捌归,dispatch_async(dispatch_get_main_queue(), ^{});
延遲執(zhí)行代碼(延遲·可以控制代碼在哪個線程執(zhí)行):
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{});
NSOperationQueue:
使用NSOperation的子類封裝操作肛响,再將操作添加到NSOperationQueue創(chuàng)建的隊列中,實現(xiàn)多線程惜索。在主線程執(zhí)行代碼特笋,只要將封裝代碼的NSOperation對象添加到主隊列就可以了。
5巾兆、控制器view的生命周期猎物?
控制器view是懶加載,用到的時候才加載角塑。
生命周期方法調(diào)用順序:
loadView-->viewDidLoad-->viewWillAppear
-->viewDidAppear-->viewWillDisappear-->viewDidDisappear
-->didReceiveMemoryWarning(收到內(nèi)存警告)
-->viewWillUnload-->viewDidUnload
6蔫磨、控制器View的加載過程?
當(dāng)程序訪問了控制器的View屬性時會先判斷控制器的View是否存在圃伶,如果存在就直接返回已經(jīng)存在的View堤如;
如果不存在,就會先調(diào)用loadView這個方法窒朋;如果控制器的loadView方法實現(xiàn)了搀罢,就會按照loadView方法加載自定義的View;
如果控制器的loadView方法沒有實現(xiàn)就會判斷storyboard是否存在侥猩;
如果storyboard存在就會按照storyboard加載控制器的View榔至;如果storyboard不存在,就會創(chuàng)建一個空視圖返回欺劳。
7唧取、iOS開發(fā)中數(shù)據(jù)存儲的方法?
常見存儲方法有三種:plist存儲划提、偏好設(shè)置(NSUserDefaults)和歸檔枫弟。
屬性列表(plist)存儲:
適用對象:只有帶有writeToFil方法的對象才能用這種方法,比如NSString腔剂、、NSArray驼仪、NSDictionary掸犬、NSSet、NSNumber绪爸、NSData等湾碎,不能存儲自定義的對象
存儲方法:
調(diào)用對象的writeToFile...方法就可以寫入文件
讀取方法:
調(diào)用對象的...WithContentsOfFile方法就可以從文件中讀取對象內(nèi)容
偏好設(shè)置(NSUserDefaults):
適用對象:使用NSUserDefaults,存儲用戶關(guān)于應(yīng)用的偏好設(shè)置奠货,本質(zhì)上仍然是plist存儲介褥,不能存儲自定義的OC對象
存儲方法:
利用NSUserDefaults的setObject等方法進(jìn)行存儲
讀取方法:
利用NSUserDefaults的objectForKey等方法進(jìn)行讀取
歸檔(NSKeyedArchiver):
適用對象:可以存儲自定義的對象,只有遵守了NSCoding協(xié)議的對象才可以
存儲方法(歸檔):
調(diào)用NSKeyedArchiver的archiverRootObject: toFile: 方法存儲對象,archiverRootObject執(zhí)行這個方法時柔滔,底層就會調(diào)用要存的對象的encodeWithCoder方法溢陪,
調(diào)用encodeWithCoder目的就是想詢問下要存對象的哪些屬性
讀取方法(解檔):
調(diào)用NSKeyedArchiver的unarchiverObjectWithFile:方法,執(zhí)行enachiverObjectWithFile:方法時就會調(diào)用initWithCoder:方法睛廊,
調(diào)用initWithCoder:方法目的就是詢問下要讀的對象有那些屬性要讀形真,怎么讀。
注意:
當(dāng)有繼承關(guān)系時超全,必須調(diào)用父類的歸檔解檔方法咆霜,當(dāng)有組合包含關(guān)系時,也必須實現(xiàn)所包含對象類的歸檔解檔方法嘶朱。
8蛾坯、為什么很多內(nèi)置類如UITableViewController的delegate屬性都是weak而不是strong?
會引起循環(huán)引用的問題疏遏。
UITableViewController內(nèi)部有一個強(qiáng)指針tableView屬性脉课,
tableView指針指向一個UITableView,UITableView內(nèi)部有一個強(qiáng)指針subviews屬性改览,
指向一個裝著UITableView全部的子控件的強(qiáng)指針數(shù)組下翎,數(shù)組中又有強(qiáng)指針指向UITableView中存在的子控件宝当。
tableView內(nèi)部有一個指針delegate视事,tableView的delegate就是控制器本身,二者相互引用庆揩,
如果delegate屬性是strong就會引起循環(huán)應(yīng)用俐东,造成內(nèi)存泄露,因此必須有一個對象是弱指針订晌,所以delegate是weak虏辫。
9、UI控件為什么不用strong用weak锈拨?
控制器有個強(qiáng)指針View屬性砌庄,View屬性指向內(nèi)存中的一個UIView,UIView內(nèi)部有一個強(qiáng)指針subviews屬性奕枢,
指向一個裝著UIView全部的子控件的強(qiáng)指針數(shù)組娄昆,數(shù)組中又有強(qiáng)指針指向UIView中存在的子控件。
所以缝彬,只要控制器在萌焰,View就在,View中的子控件就在谷浅,所以扒俯,ui控件沒必要用強(qiáng)指針奶卓,用weak就可以。
10撼玄、block使用時的注意點夺姑?
Block可以使用在定義之前聲明的局部變量。
int i = 10;
void(^myBlock)() = ^{
NSLog(@"%d", i);
};
i = 100;
myBlock();
注意:
在定義Block時互纯,會在Block中建立當(dāng)前局部變量內(nèi)容的副本(拷貝)瑟幕。
后續(xù)再對該變量的數(shù)值進(jìn)行修改,不會影響B(tài)lock中的數(shù)值留潦。
以上代碼輸出結(jié)果為10只盹。
如果需要在block中保持局部變量的數(shù)值變化,需要使用__block關(guān)鍵字兔院。使用__block關(guān)鍵字后殖卑,同樣可以在Block中修改該變量的數(shù)值。
將第一行代碼改為: __block int i = 10;后坊萝,輸出結(jié)果就變成了100孵稽;
另外:block代碼塊中不能直接用點語法調(diào)用self的方法,會造成循環(huán)引用十偶,要用中括號調(diào)用菩鲜。
11、如何對UITableView進(jìn)行優(yōu)化惦积?
UITableViewCell的重用原理:
當(dāng)滾動列表時接校,部分UITableViewCell會移出窗口,UITableView會將窗口外的UITableViewCell放入一個對象池中狮崩,等待重用蛛勉。
當(dāng)UITableView要求dataSource返回UITableViewCell時,dataSource會先查看這個對象池睦柴,如果池中有未使用的UITableViewCell诽凌,
dataSource會用新的數(shù)據(jù)配置這個UITableViewCell,然后返回給UITableView坦敌,重新顯示到窗口中侣诵,從而避免創(chuàng)建新對象。
還有一個非常重要的問題:有時候需要自定義UITableViewCell(用一個子類繼承UITableViewCell)狱窘,
而且每一行用的不一定是同一種UITableViewCell(如短信聊天布局)杜顺,所以一個UITableView可能擁有不同類型的UITableViewCell,
對象池中也會有很多不同類型的UITableViewCell训柴,時可能會得到錯誤類型的UITableViewCell那么UITableView在重用UITableViewCell哑舒。
解決方案:UITableViewCell有個NSString *reuseIdentifier屬性妇拯,可以在初始化UITableViewCell的時候傳入一個特定的字符串標(biāo)識來設(shè)置reuseIdentifier(一般用UITableViewCell的類名)幻馁。
當(dāng)UITableView要求dataSource返回UITableViewCell時洗鸵,
先通過一個字符串標(biāo)識到對象池中查找對應(yīng)類型的UITableViewCell對象,
如果有仗嗦,就重用膘滨,如果沒有,就傳入這個字符串標(biāo)識來初始化一個UITableViewCell對象稀拐。
12火邓、UIView動畫與核心動畫的區(qū)別?
UIView動畫與核心動畫的區(qū)別:
1德撬、核心動畫只作用在CALayer上面铲咨,UIView是沒有辦法使用核心動畫的
2、核心動畫看到的都是假象蜓洪,并沒有修改UIView的真實位置
什么時候使用UIView動畫纤勒?
需要與用戶進(jìn)行交互的時候使用UIView動畫,如果不需要與用戶進(jìn)行交互隆檀,兩者都可以使用摇天。
什么時候使用核心動畫?
1恐仑、根據(jù)路徑做動畫泉坐,要使用核心動畫(幀動畫)
2、做轉(zhuǎn)場動畫時裳仆,也要使用核心動畫
13腕让、自定義視圖中重寫layoutsubView需要調(diào)用父類的layoutsubView嗎,為什么鉴逞?
如果重寫的控件是UIView不調(diào)用父類的layoutsubView也沒關(guān)系记某,里面沒有任何子控件,所以不會做什么事情构捡。一般系統(tǒng)自帶視圖中有子控件的都會重寫layoutSubviews方法液南,因此我們自定義系統(tǒng)自帶控件并且重寫layoutSubviews必須調(diào)用[super layoutSubviews],先布局系統(tǒng)自帶子控件的位置和尺寸,才設(shè)置我們自己的控件位置和尺寸勾徽。否則會發(fā)現(xiàn)想用系統(tǒng)自帶視圖的子控件的時候滑凉,會出現(xiàn)意想不到的效果。
1
14喘帚、應(yīng)用程序的啟動流程畅姊?
1.執(zhí)行Main
2.執(zhí)行UIApplicationMain函數(shù).
3.創(chuàng)建UIApplication對象,并設(shè)置UIApplicationMain對象的代理.
UIApplication的第三個參數(shù)就是UIApplication的名稱,如果指定為nil,它會默認(rèn)為UIApplication.
UIApplication的第四個參數(shù)為UIApplication的代理.
4.開啟一個主運行循環(huán).保證應(yīng)用程序不退出.
5.加載info.plist.加載配置文件.判斷一下info.plist文件當(dāng)中有沒有Main storyboard file base name里面有沒有指定storyboard文件,如果有就去加載info.plist文件,如果沒有,那么應(yīng)用程序加載完畢.
15、NSString 的時候用copy和strong的區(qū)別吹由?
OC中NSString為不可變字符串的時候若未,用copy和strong都是只分配一次內(nèi)存,但是如果用copy的時候倾鲫,需要先判斷字符串是否是不可變字符串粗合,如果是不可變字符串萍嬉,就不再分配空間,如果是可變字符串才分配空間隙疚。如果程序中用到NSString的地方特別多壤追,每一次都要先進(jìn)行判斷就會耗費性能,影響用戶體驗供屉,用strong就不會再進(jìn)行判斷行冰,所以,不可變字符串可以直接用strong伶丐。
1
16悼做、事件傳遞與響應(yīng)的完整過程?
在產(chǎn)生一個事件時,系統(tǒng)會將該事件加入到一個由UIApplication管理的事件隊列中,
UIApplication會從事件隊列中取出最前面的事件,將它傳遞給先發(fā)送事件給應(yīng)用程序的主窗口.
主窗口會調(diào)用hitTest方法尋找最適合的視圖控件,找到后就會調(diào)用視圖控件的touches方法來做具體的事情.
當(dāng)調(diào)用touches方法,它的默認(rèn)做法, 就會將事件順著響應(yīng)者鏈條往上傳遞,
傳遞給上一個響應(yīng)者,接著就會調(diào)用上一個響應(yīng)者的touches方法
17.ASIHttpRequest哗魂、AFNetWorking之間的區(qū)別?
ASIHttpRequest功能強(qiáng)大贿堰,主要是在MRC下實現(xiàn)的,是對系統(tǒng)CFNetwork API進(jìn)行了封裝啡彬,支持HTTP協(xié)議的CFHTTP羹与,配置比較復(fù)雜,并且ASIHttpRequest框架默認(rèn)不會幫你監(jiān)聽網(wǎng)絡(luò)改變庶灿,如果需要讓ASIHttpRequest幫你監(jiān)聽網(wǎng)絡(luò)狀態(tài)改變纵搁,并且手動開始這個功能。
AFNetWorking構(gòu)建于NSURLConnection往踢、NSOperation以及其他熟悉的Foundation技術(shù)之上腾誉。擁有良好的架構(gòu),豐富的API及模塊構(gòu)建方式峻呕,使用起來非常輕松利职。它基于NSOperation封裝的,AFURLConnectionOperation子類瘦癌。
ASIHttpRequest是直接操作對象ASIHttpRequest是一個實現(xiàn)了NSCoding協(xié)議的NSOperation子類猪贪;AFNetWorking直接操作對象的AFHttpClient,是一個實現(xiàn)NSCoding和NSCopying協(xié)議的NSObject子類讯私。
同步請求:ASIHttpRequest直接通過調(diào)用一個startSynchronous方法热押;AFNetWorking默認(rèn)沒有封裝同步請求,如果開發(fā)者需要使用同步請求斤寇,則需要重寫getPath:paraments:success:failures方法桶癣,對于AFHttpRequestOperation進(jìn)行同步處理。
性能對比:AFNetworking請求優(yōu)于ASIHttpRequest娘锁;
18.如何進(jìn)行真機(jī)調(diào)試牙寞?
1.首先需要用鑰匙串創(chuàng)建一個鑰匙(key);
2.將鑰匙串上傳到官網(wǎng)莫秆,獲取iOS Development證書间雀;
3.創(chuàng)建App ID即我們應(yīng)用程序中的Boundle ID尤慰;
4.添加Device ID即UDID;
5.通過勾選前面所創(chuàng)建的證書:App ID雷蹂、Device ID;
6.生成mobileprovision文件杯道;
7.先決條件:申請開發(fā)者賬號 99美刀
19.APP發(fā)布的上架流程?
1.登錄應(yīng)用發(fā)布網(wǎng)站添加應(yīng)用信息匪煌;
2.下載安裝發(fā)布證書;
3.選擇發(fā)布證書党巾,使用Archive編譯發(fā)布包萎庭,用Xcode將代碼(發(fā)布包)上傳到服務(wù)器;
4.等待審核通過;
5.生成IPA:菜單欄->Product->Archive.
20.能否向編譯后得到的類中增加實例變量齿拂?能否向運行時創(chuàng)建的類中添加實例變量驳规?為什么?
- 不能向編譯后得到的類中增加實例變量署海;
- 能向運行時創(chuàng)建的類中添加實例變量吗购;
解釋如下:
因為編譯后的類已經(jīng)注冊在 runtime 中,類結(jié)構(gòu)體中的 objc_ivar_list 實例變量的鏈表 和 instance_size 實例變量的內(nèi)存大小已經(jīng)確定砸狞,同時runtime 會調(diào)用 class_setIvarLayout 或 class_setWeakIvarLayout 來處理 strong weak 引用捻勉。所以不能向存在的類中添加實例變量;
運行時創(chuàng)建的類是可以添加實例變量刀森,調(diào)用 class_addIvar 函數(shù)踱启。但是得在調(diào)用 objc_allocateClassPair 之后,objc_registerClassPair 之前研底,原因同上埠偿。
21.以+ scheduledTimerWithTimeInterval…的方式觸發(fā)的timer,在滑動頁面上的列表時榜晦,timer會暫定回調(diào)冠蒋,為什么?如何解決乾胶?
RunLoop只能運行在一種mode下浊服,如果要換mode,當(dāng)前的loop也需要停下重啟成新的胚吁。利用這個機(jī)制牙躺,ScrollView滾動過程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode會切換到UITrackingRunLoopMode來保證ScrollView的流暢滑動:只能在NSDefaultRunLoopMode模式下處理的事件會影響ScrollView的滑動。
如果我們把一個NSTimer對象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主運行循環(huán)中的時候, ScrollView滾動過程中會因為mode的切換腕扶,而導(dǎo)致NSTimer將不再被調(diào)度孽拷。
同時因為mode還是可定制的,所以:
Timer計時會被scrollView的滑動影響的問題可以通過將timer添加到NSRunLoopCommonModes(kCFRunLoopCommonModes)來解決半抱。代碼如下:
//將timer添加到NSDefaultRunLoopMode中
[NSTimer scheduledTimerWithTimeInterval: target: selector:@selector(timerTick:) userInfo: repeats:];
//然后再添加到NSRunLoopCommonModes里
NSTimer *timer = [NSTimer timerWithTimeInterval: target: selector:@selector(timerTick:) userInfo: repeats:];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
22.runloop和線程有什么關(guān)系脓恕?
總的說來膜宋,Run loop,正如其名炼幔,loop表示某種循環(huán)秋茫,和run放在一起就表示一直在運行著的循環(huán)。實際上乃秀,run loop和線程是緊密相連的肛著,可以這樣說run loop是為了線程而生,沒有線程跺讯,它就沒有存在的必要枢贿。Run loops是線程的基礎(chǔ)架構(gòu)部分, Cocoa 和 CoreFundation 都提供了 run loop 對象方便配置和管理線程的 run loop (以下都以 Cocoa 為例)刀脏。每個線程局荚,包括程序的主線程( main thread )都有與之相應(yīng)的 run loop 對象。
runloop 和線程的關(guān)系:
主線程的run loop默認(rèn)是啟動的愈污。
iOS的應(yīng)用程序里面耀态,程序啟動后會有一個如下的main()函數(shù)
( argc, * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, , NSStringFromClass([AppDelegate class]));
}
}
重點是UIApplicationMain()函數(shù),這個方法會為main thread設(shè)置一個NSRunLoop對象暂雹,這就解釋了:為什么我們的應(yīng)用可以在無人操作的時候休息茫陆,需要讓它干活的時候又能立馬響應(yīng)。對其它線程來說擎析,run loop默認(rèn)是沒有啟動的簿盅,如果你需要更多的線程交互則可以手動配置和啟動,如果線程只是去執(zhí)行一個長時間的已確定的任務(wù)則不需要揍魂。
在任何一個 Cocoa 程序的線程中桨醋,都可以通過以下代碼來獲取到當(dāng)前線程的 run loop 。
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
23.如何用GCD同步若干個異步調(diào)用现斋?(如根據(jù)若干個url異步加載多張圖片喜最,然后在都下載完成后合成一張整圖)
使用Dispatch Group追加block到Global Group Queue,這些block如果全部執(zhí)行完畢,就會執(zhí)行Main Dispatch Queue中的結(jié)束處理的block庄蹋。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, );
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{ /*加載圖片1 / });
dispatch_group_async(group, queue, ^{ /加載圖片2 / });
dispatch_group_async(group, queue, ^{ /加載圖片3 */ });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 合并圖片
});
24.HTTP協(xié)議的特點瞬内,關(guān)于HTTP請求GET和POST的區(qū)別?
HTTP協(xié)議的特點:
- HTTP超文本傳輸協(xié)議,是短連接限书,是客戶端主動發(fā)送請求虫蝶,服務(wù)器做出響應(yīng),服務(wù)器響應(yīng)之后倦西,鏈接斷開能真。HTTP是一個屬于應(yīng)用層面向?qū)ο蟮膮f(xié)議,HTTP有兩類報文:請求報文和響應(yīng)報文。
- HTTP請求報文:一個HTTP請求報文由請求行粉铐、請求頭部疼约、空行和請求數(shù)據(jù)4部分組成。
- HTTP響應(yīng)報文:由三部分組成:狀態(tài)行蝙泼、消息報頭程剥、響應(yīng)正文。
GET和POST的區(qū)別: - GET請求:參數(shù)在地址后拼接汤踏,沒有請求數(shù)據(jù)织鲸,不安全(因為所有參數(shù)都拼接在地址后面),不適合傳輸大量數(shù)據(jù)(長度有限制茎活,為1024個字節(jié))。
GET提交琢唾、請求的數(shù)據(jù)會附在URL之后载荔,即把數(shù)據(jù)放置在HTTP協(xié)議頭中。以采桃?分割URL和傳輸數(shù)據(jù)懒熙,多個參數(shù)用&連接。如果數(shù)據(jù)是英文字母或數(shù)字普办,原樣發(fā)送工扎,如果是空格,轉(zhuǎn)換為+衔蹲,如果是中文/其他字符肢娘,則直接把字符串用BASE64加密。 - POST請求:參數(shù)在請求數(shù)據(jù)區(qū)放著舆驶,相對GET請求更安全橱健,并且數(shù)據(jù)大小沒有限制。把提交的數(shù)據(jù)放置在HTTP包的包體中.
- GET提交的數(shù)據(jù)會在地址欄顯示出來沙廉,而POST提交拘荡,地址欄不會改變。
傳輸數(shù)據(jù)的大星肆辍:
- GET提交時珊皿,傳輸數(shù)據(jù)就會受到URL長度限制,POST由于不是通過URL傳值巨税,理論上書不受限蟋定。
- POST的安全性要比GET的安全性高;
- 通過GET提交數(shù)據(jù)草添,用戶名和密碼將明文出現(xiàn)在URL上溢吻,比如登陸界面有可能被瀏覽器緩存。
25.如何理解MVC設(shè)計模式?
MVC是一種架構(gòu)模式,M表示MOdel促王,V表示視圖View犀盟,C表示控制器Controller:
- Model負(fù)責(zé)存儲、定義蝇狼、操作數(shù)據(jù)阅畴;
- View用來展示書給用戶,和用戶進(jìn)行操作交互迅耘;
- Controller是Model和View的協(xié)調(diào)者贱枣,Controller把Model中的數(shù)據(jù)拿過來給View用。Controller可以直接與Model和View進(jìn)行通信颤专,而View不能和Controller直接通信纽哥。View與Controller通信需要利用代理協(xié)議的方式,當(dāng)有數(shù)據(jù)更新時栖秕,Model也要與Controller進(jìn)行通信春塌,這個時候就要用Notification和KVO,這個方式就像一個廣播一樣簇捍,MOdel發(fā)信號只壳,Controller設(shè)置監(jiān)聽接受信號,當(dāng)有數(shù)據(jù)更新時就發(fā)信號給Controller暑塑,Model和View不能直接進(jìn)行通信吼句,這樣會違背MVC設(shè)計模式。
26.線程與進(jìn)程的區(qū)別和聯(lián)系?
- 一個程序至少要有進(jìn)城,一個進(jìn)程至少要有一個線程事格。
- 進(jìn)程:資源分配的最小獨立單元,進(jìn)程是具有一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運行活動,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨立單位惕艳。
- 線程:進(jìn)程下的一個分支,是進(jìn)程的實體,是CPU調(diào)度和分派的基本單元,它是比進(jìn)程更小的能獨立運行的基本單位,線程自己基本不擁有系統(tǒng)資源,只擁有一點在運行中必不可少的資源(程序計數(shù)器、一組寄存器驹愚、棧)尔艇,但是它可與同屬一個進(jìn)程的其他線程共享進(jìn)程所擁有的全部資源。
- 進(jìn)程和線程都是由操作系統(tǒng)所體會的程序運行的基本單元么鹤,系統(tǒng)利用該基本單元實現(xiàn)系統(tǒng)對應(yīng)用的并發(fā)性终娃。
- 進(jìn)程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。進(jìn)程有獨立的地址空間蒸甜,一個進(jìn)程崩潰后棠耕,在保護(hù)模式下不會對其它進(jìn)程產(chǎn)生影響,而線程只是一個進(jìn)程中的不同執(zhí)行路徑柠新。線程有自己的堆棧和局部變量窍荧,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進(jìn)程死掉恨憎,所以多進(jìn)程的程序要比多線程的程序健壯蕊退,但在進(jìn)程切換時郊楣,耗費資源較大,效率要差一些瓤荔。
- 但對于一些要求同時進(jìn)行并且又要共享某些變量的并發(fā)操作净蚤,只能用線程,不能用進(jìn)程输硝。