最近在簡書上看到一篇大牛@J_Knight寫的面試題, 發(fā)現(xiàn)好多知識點都比較模糊,所有就去各種找答案總結(jié)一下,記錄一下以后備用~~
如有侵權(quán),告知即刪!
一.基礎(chǔ)篇
1:為什么說objective -C 是一門動態(tài)語言?
(1):Objective-C具有相當(dāng)多的動態(tài)特性,表現(xiàn)為三方面:動態(tài)類型(Dynamic typing)羔杨、動態(tài)綁定(Dynamic binding)和動態(tài)加載(Dynamic loading)娇澎。動態(tài)——必須到運行時(run time)才會做的一些事情。
(2):動態(tài)類型:即運行時再決定對象的類型钟鸵,這種動態(tài)特性在日常的應(yīng)用中非常常見,簡單來說就是id類型。事實上,由于靜態(tài)類型的固定性和可預(yù)知性陌宿,從而使用的更加廣泛。靜態(tài)類型是強類型波丰,而動態(tài)類型屬于弱類型壳坪,運行時決定接受者。
(3:)動態(tài)綁定:基于動態(tài)類型掰烟,在某個實例對象被確定后爽蝴,其類型便被確定了,該對象對應(yīng)的屬性和響應(yīng)消息也被完全確定媚赖。
(4):動態(tài)加載:根據(jù)需求加載所需要的資源霜瘪,最基本就是不同機(jī)型的適配,例如惧磺,在Retina設(shè)備上加載@2x的圖片,而在老一些的普通蘋設(shè)備上加載原圖捻撑,讓程序在運行時添加代碼模塊以及其他資源磨隘,用戶可根據(jù)需要加載一些可執(zhí)行代碼和資源,而不是在啟動時就加載所有組件顾患,可執(zhí)行代碼可以含有和程序運行時整合的新類番捂。
2:講一下MVC和MVVM,MVP江解?
(1):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è)計模式管闷。
(2):如何理解MVVM設(shè)計模式
ViewModel層粥脚,就是View和Model層的粘合劑,他是一個放置用戶輸入驗證邏輯包个,視圖顯示邏輯刷允,發(fā)起網(wǎng)絡(luò)請求和其他各種各樣的代碼的極好的地方。說白了碧囊,就是把原來ViewController層的業(yè)務(wù)邏輯和頁面邏輯等剝離出來放到ViewModel層树灶。
View層,就是ViewController層糯而,他的任務(wù)就是從ViewModel層獲取數(shù)據(jù)天通,然后顯示。
(3):如何理解MVP設(shè)計模式(沒用過,找了一下概念)
從字面意思來理解熄驼,MVP即Modal View Presenter(模型 視圖 協(xié)調(diào)器)像寒,MVP實現(xiàn)了Cocoa的MVC的愿景。MVP的協(xié)調(diào)器Presenter并沒有對ViewController的聲明周期做任何改變瓜贾,因此View可以很容易的被模擬出來诺祸。在Presenter中根本沒有和布局有關(guān)的代碼,但是它卻負(fù)責(zé)更新View的數(shù)據(jù)和狀態(tài)祭芦。
MVP 是第一個如何協(xié)調(diào)整合三個實際上分離的層次的架構(gòu)模式筷笨,既然我們不希望 View 涉及到 Model,那么在顯示的 View Controller(其實就是 View)中處理這種協(xié)調(diào)的邏輯就是不正確的龟劲,因此我們需要在其他地方來做這些事情胃夏。例如,我們可以做基于整個 App 范圍內(nèi)的路由服務(wù)咸灿,由它來負(fù)責(zé)執(zhí)行協(xié)調(diào)任務(wù)构订,以及 View 到 View 的展示。這個出現(xiàn)并且必須處理的問題不僅僅是在 MVP 模式中避矢,同時也存在于以下集中方案中悼瘾。
MVC和MVP的區(qū)別就是囊榜,在MVP中M和V沒有直接通信。
3:為什么代理要用weak亥宿?代理的delegate和dataSource有什么區(qū)別卸勺?block和代理的區(qū)別?
(1) weak是弱引用,一旦不進(jìn)行使用后,永遠(yuǎn)不會使用了烫扼,就不會產(chǎn)生野指針,也不會造成內(nèi)存泄露問題.
在說下weak和assign的區(qū)別: weak和assign都不會增加引用計數(shù)曙求,區(qū)別是修飾的對象在釋放時所做的操作不同,weak是會把對象置為nil映企,assign則不會悟狱,assign一般適用與基本數(shù)據(jù)類型
(2):代理的delegate和dataSource有什么區(qū)別:一般比較熟悉的就是應(yīng)用在UITableView中.
UITableView需要一個數(shù)據(jù)源(dataSource)來顯示數(shù)據(jù),UITableView會向數(shù)據(jù)源查詢一共有多少行數(shù)據(jù)以及每一行顯示什么數(shù)據(jù)等堰氓。沒有設(shè)置數(shù)據(jù)源的UITableView只是個空殼挤渐。凡是遵守UITableViewDataSource協(xié)議的OC對象,都可以是UITableView的數(shù)據(jù)源双絮。
通常都要為UITableView設(shè)置代理對象(delegate)浴麻,以便在UITableView觸發(fā)一下事件時做出相應(yīng)的處理,比如選中了某一行囤攀。凡是遵守了UITableViewDelegate協(xié)議的OC對象软免,都可以是UITableView的代理對象。一般會讓控制器充當(dāng)UITableView的dataSource和delegate
(3):block和代理的區(qū)別,一般還會加上Notification,所以一起記錄下
blockblock被ObjC看成是對象焚挠,它封裝了一段代碼膏萧,這段代碼可以在任何時候執(zhí)行。Blocks可以作為函數(shù)參數(shù)或者函數(shù)的返回值蝌衔,而其本身又可以帶輸入?yún)?shù)或返回值向抢。它和傳統(tǒng)的函數(shù)指針很類似,但是有區(qū)別:blocks是inline的胚委,并且它對局部變量是只讀的。block類似一些其它Web編程語言中的“匿名函數(shù)”叉信。在objc中通常使用block實現(xiàn)代理方法實現(xiàn)的功能亩冬,也就是回調(diào)。使用代理需要設(shè)置代理的數(shù)據(jù)接收者硼身,而且代理方法是被分離開來處理的硅急,block可以將這些分離的代碼放到一個代碼塊中。
delegatedelegate,又稱委托或者代理,它是一種設(shè)計模式.delegate主要是用于兩個對象之間的交互,并且解除兩個通信對象的耦合性,iOS大量使用代理模式,主要是用于視圖與使用對象之間的通信交互.
官方文檔翻譯解釋:
代理是一種簡單而功能強大的設(shè)計模式佳遂,這種模式用于一個對象“代表”另外一個對象和程序中其他的對象進(jìn)行交互营袜。 主對象(這里指的是delegating object)中維護(hù)一個代理(delegate)的引用并且在合適的時候向這個代理發(fā)送消息。這個消息通知“代理”主對象即將處理或是已經(jīng)處理完了某一個事件丑罪。這個代理可以通過更新自己或是其它對象的UI界面或是其它狀態(tài)來響應(yīng)主對象所發(fā)送過來的這個事件的消息荚板》锉冢或是在某些情況下能返回一個值來影響其它即將發(fā)生的事件該如何來處理。代理的主要價值是它可以讓你容易的定制各種對象的行為跪另。注意這里的代理是個名詞拧抖,它本身是一個對象,這個對象是專門代表被代理對象來和程序中其他對象打交道的免绿。委托是objC中使用非常頻繁的一種設(shè)計模式唧席,它的實現(xiàn)與協(xié)議的使用是分不開的.
Notification通知中心概述:通知中心實際上是在程序內(nèi)部提供了消息廣播的一種機(jī)制。通知中心不能在進(jìn)程間進(jìn)行通信嘲驾。實際上就是一個二傳手淌哟,把接收到的消息,根據(jù)內(nèi)部的一個消息轉(zhuǎn)發(fā)表辽故,來將消息轉(zhuǎn)發(fā)給需要的對象徒仓。通知中心是基于觀察者模式的,它允許注冊榕暇、刪除觀察者蓬衡。一個NSNotificationCenter可以有許多的通知消息NSNotification,對于每一個NSNotification可以有很多的觀察者Observer來接收通知彤枢。
使用區(qū)別
delegate與block一般用于兩個對象1對1之間的通信交互狰晚、delegate需要定義協(xié)議方法,代理對象需要實現(xiàn)協(xié)議方法并且需要建立代理關(guān)系才可以實現(xiàn)通信缴啡。 block更加簡潔壁晒,不需要定義繁瑣的協(xié)議方法,但是如果通信時間比較多的話,建議使用delgate。 Notfication主要用于1對多的通信业栅,而且通信對象之間不需要建立關(guān)系秒咐,但是使用通知,代碼的可讀性差碘裕。
4:屬性的實質(zhì)是什么携取?包括哪幾個部分?屬性默認(rèn)的關(guān)鍵字都有哪些帮孔?@dynamic關(guān)鍵字和@synthesize關(guān)鍵字是用來做什么的雷滋?屬性的默認(rèn)關(guān)鍵字是什么?
(1):屬性的實質(zhì)是什么:其實不太懂這個實質(zhì)是什么意思,一般屬性是一個類中用來描述對象的抽象概念,一個類可以有很多屬性文兢,一個屬性可以描述對象的一個特征.包括:實例變量,setter/getter方法.
(2)屬性的關(guān)鍵字:經(jīng)常使用的關(guān)鍵字有strong晤斩,weak,assign姆坚,copy澳泵,nonatomic,atomic....等兼呵。
(3)@dynamic關(guān)鍵字:是開發(fā)者自已提供相應(yīng)的屬性聲明,@dynamic意思是由開發(fā)人員提供相應(yīng)的代碼:對于只讀屬性需要提供setter兔辅,對于讀寫屬性需要提供 setter 和getter腊敲。查閱了一些資料確定@dynamic的意思是告訴編譯器,屬性的獲取與賦值方法由用戶自己實現(xiàn), 不自動生成。
(4)@synthesize關(guān)鍵字:是系統(tǒng)自動生成getter和setter屬性聲明;@synthesize的意思是幢妄,除非開發(fā)人員已經(jīng)做了兔仰,否則由編譯器生成相應(yīng)的代碼,以滿足屬性聲明蕉鸳;
(5):屬性的默認(rèn)關(guān)鍵字是什么(這個不太明白什么意思,求答案?)
5:NSString為什么要用copy關(guān)鍵字乎赴,如果用strong會有什么問題?(注意:這里沒有說用strong就一定不行潮尝。使用copy和strong是看情況而定的)
(1).因為父類指針可以指向子類對象,使用 copy 的目的是為了讓本對象的屬性不受外界影響,使用 copy 無論給我傳入是一個可變對象還是不可對象,我本身持有的就是一個不可變的副本.
(2).如果我們使用是 strong ,那么這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那么會影響該屬性.
這個例子就非常清楚:原文鏈接
如下所示榕吼,當(dāng)修飾符為copy時,因為NSMutableString是NSString類型的子類勉失,所以可以用指針self.name指向mStr羹蚣,但是我們知道copy的含義是指當(dāng)重新賦值時深拷貝新對象再賦值給self.name.
所以此時self.name的指針和mStr的指針指向的對象就不同了,所以當(dāng)給mStr對象發(fā)送方法appendString的時候乱凿,修改的只是mStr(此時的值變?yōu)閙utablestring----addstring)顽素,而self.name依然不變(mutablestring----);相反當(dāng)修飾符為strong時,因為strong的意思是指針指向原對象徒蟆,并且引用計數(shù)+1胁出,所以self.name和mStr指向同一個對象,當(dāng)修改mStr時self.name也會一起變化段审。所以為了避免NSString類型的值被修改全蝶,一般建議用copy修飾符修飾。
@interface ViewController ()
@property (nonatomic,copy) NSString *name;
//@property (nonatomic,strong) NSString *name;
@end
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableString *mStr = [NSMutableString stringWithFormat:@"mutablestring----"];
[self.name](http://self.name) = mStr;
[mStr appendString:@"addstriing"];//name的修飾符為copy時寺枉,name的結(jié)果為mutablestring----
NSLog(@"%@",mStr);//name的修飾符為strong時抑淫,name的結(jié)果為mutablestring----addstriing
NSLog(@"%@",[self.name](http://self.name));
6: 如何令自己所寫的對象具有拷貝功能?
若想令自己所寫的對象具有拷貝功能,則需實現(xiàn) NSCopying 協(xié)議姥闪。如果自定義的對象分為可變版本與不可變版本始苇,那么就要同時實現(xiàn) NSCopying與 NSMutableCopying協(xié)議。
具體步驟:
需聲明該類遵從 NSCopying 協(xié)議
實現(xiàn) NSCopying 協(xié)議筐喳。該協(xié)議只有一個方法:- (id)copyWithZone:(NSZone *)zone;
7:可變集合類 和 不可變集合類的 copy 和 mutablecopy有什么區(qū)別埂蕊?如果是集合是內(nèi)容復(fù)制的話,集合里面的元素也是內(nèi)容復(fù)制么疏唾?
(1)這里主要涉及到iOS 的深淺拷貝這里有篇很好的參考文章,我先總結(jié)下回答上面的問題:
可變集合不管是copy還是mutableCopy都會產(chǎn)生新對象(內(nèi)容拷貝)
不可變集合copy是淺拷貝(指針拷貝)不會產(chǎn)生新對象,mutableCopy是深拷貝會產(chǎn)生新對象(內(nèi)容拷貝)
如果是深拷貝集合里面的元素內(nèi)容也是內(nèi)容復(fù)制.
8:為什么IBOutlet修飾的UIView也適用weak關(guān)鍵字?
參考鏈接
文章告訴我們:
因為既然有外鏈那么視圖在xib或者storyboard中肯定存在函似,視圖已經(jīng)對它有一個強引用了槐脏。
不過這個回答漏了個重要知識,使用storyboard(xib不行)創(chuàng)建的vc撇寞,會有一個叫_topLevelObjectsToKeepAliveFromStoryboard的私有數(shù)組強引用所有top level的對象顿天,所以這時即便outlet聲明成weak也沒關(guān)系.
9:nonatomic和atomic的區(qū)別堂氯?atomic是絕對的線程安全么?為什么牌废?如果不是咽白,那應(yīng)該如何實現(xiàn)?
atomic:默認(rèn)是有該屬性的鸟缕,這個屬性是為了保證程序在多線程情況下晶框,編譯器會自動生成一些互斥加鎖代碼,避免該變量的讀寫不同步問題懂从。nonatomic:如果該對象無需考慮多線程的情況授段,請加入這個屬性,這樣會讓編譯器少生成一些互斥加鎖代碼番甩,可以提高效率侵贵。
在iOS中使用同步鎖的開銷比較大, 這會帶來性能問題缘薛。一般情況下并不要求屬性必須是“原子的”窍育,因為這并不能保證“線程安全”(thread safety),若要實現(xiàn)“線程安全”的操作宴胧,還需采用更為深層的鎖定機(jī)制才醒漱抓。(具體怎么做還不清楚,沒研究過)
例如:一個線程在連續(xù)多次讀取某個屬性值的過程中有別的線程在同時改寫該值,那么即便將屬性聲明為atomic牺汤,也還是會讀取到不同的屬性值辽旋。
10:UICollectionView自定義layout如何實現(xiàn)?
項目中并沒用到需要自定義layout的地方,度娘出一篇詳解文章奉上鏈接
11:用StoryBoard開發(fā)界面有什么弊端檐迟?如何避免补胚?
(1)項目中用到StoryBoard的地方較多談下想法,首先團(tuán)隊開發(fā)中用StoryBoard,如果模塊劃分的不是那么獨立,會有多人共同寫一個模塊的情況,那最后不要用StoryBoard,應(yīng)為SVN經(jīng)常會沖突導(dǎo)致更新下的代碼會有問題,可能需要恢復(fù)到上導(dǎo)致沖突前一版本才能解決,這樣如果我們有要提交的代碼可能就需要苦逼的在寫一次(想當(dāng)年我們小組6個人共同開發(fā)是,就被一小伙伴坑慘了).但是如果模塊劃分的比較獨立的話可以每個人各自創(chuàng)建一個StoryBoard,想怎么玩都沒事.還有別的小伙伴提議每個類都創(chuàng)建一個StoryBoard,這樣我并不贊成,不過你喜歡就好~.
12:進(jìn)程和線程的區(qū)別?同步異步的區(qū)別追迟?并行和并發(fā)的區(qū)別溶其?
(1)進(jìn)程:資源分配的最小獨立單元,進(jìn)程是具有一定獨立功能的程序關(guān)于某個數(shù)據(jù)集合上的一次運行活動,進(jìn)程是系統(tǒng)進(jìn)行資源分配和調(diào)度的一個獨立單位.
(2)線程:進(jìn)程下的一個分支,是進(jìn)程的實體,是CPU調(diào)度和分派的基本單元,它是比進(jìn)程更小的能獨立運行的基本單位,線程自己基本不擁有系統(tǒng)資源,只擁有一點在運行中必不可少的資源(程序計數(shù)器、一組寄存器敦间、棧)瓶逃,但是它可與同屬一個進(jìn)程的其他線程共享進(jìn)程所擁有的全部資源。
(3)同步和異步:同步指第一個任務(wù)不執(zhí)行完廓块,不會開始第二個厢绝,異步是不管第一個有沒有執(zhí)行完,都開始第二個带猴。
(4):并行和并發(fā):并行性(parallelism)指兩個或兩個以上事件或活動在同一時刻發(fā)生昔汉。在多道程序環(huán)境下,并行性使多個程序同一時刻可在不同CPU上同時執(zhí)行拴清。
并發(fā)性(Concurrence):指兩個或兩個以上的事件或活動在同一時間間隔內(nèi)發(fā)生靶病。并發(fā)的實質(zhì)是一個物理CPU(也可以多個物理CPU) 在若干道程序之間多路復(fù)用会通,并發(fā)性是對有限物理資源強制行使多用戶共享以提高效率。
區(qū)別:一個處理器同時處理多個任務(wù)和多個處理器或者是多核的處理器同時處理多個不同的任務(wù)娄周。
13:線程間通信涕侈?
-
線程間通信的體現(xiàn):
(1 ).一個線程傳遞數(shù)據(jù)給另一個線程
(2).在一個線程中執(zhí)行完特定任務(wù)后,轉(zhuǎn)到另一個線程繼續(xù)執(zhí)行任務(wù)
-
線程間通信常用的方法
(1) NSThread可以先將自己的當(dāng)前線程對象注冊到某個全局的對象中去煤辨,這樣相互之間就可以獲取對方的線程對象裳涛,然后就可以使用下面的方法進(jìn)行線程間的通信了,由于主線程比較特殊掷酗,所以框架直接提供了在主線程執(zhí)行的方法
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);
用法如下:
//點擊屏幕開始執(zhí)行下載方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[self performSelectorInBackground:@selector(download) withObject:nil];
}
//下載圖片
- (void)download
{
// 1.圖片地址
NSString *urlStr = @"[http://d.jpg](http://d.jpg)";
NSURL *url = [NSURL URLWithString:urlStr];
// 2.根據(jù)地址下載圖片的二進(jìn)制數(shù)據(jù)
NSData *data = [NSData dataWithContentsOfURL:url];
NSLog(@"---end");
// 3.設(shè)置圖片
UIImage *image = [UIImage imageWithData:data];
// 4.回到主線程调违,刷新UI界面(為了線程安全)
[self performSelectorOnMainThread:@selector(downloadFinished:) withObject:image waitUntilDone:NO];
// [self performSelector:@selector(downloadFinished:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];
}
- (void)downloadFinished:(UIImage *)image
{
self.imageView.image = image;
NSLog(@"downloadFinished---%@", [NSThread currentThread]);
}
(2). GCD一個線程傳遞數(shù)據(jù)給另一個線程,如:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"donwload---%@", [NSThread currentThread]);
// 1.子線程下載圖片
NSURL *url = [NSURL URLWithString:@"[http://d.jpg](http://d.jpg)"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:data];
// 2.回到主線程設(shè)置圖片
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"setting---%@ %@",
[NSThread currentThread], image);
[self.button setImage:image forState:UIControlStateNormal];
});
});}
14:GCD的一些常用的函數(shù)泻轰?(group技肩,barrier,信號量浮声,線程同步)
GCD(Grand Central Dispatch)宏大的中央調(diào)度虚婿,串行隊列、并發(fā)隊列泳挥、主線程隊列然痊;
同步和異步:同步指第一個任務(wù)不執(zhí)行完,不會開始第二個屉符,異步是不管第一個有沒有執(zhí)行完剧浸,都開始第二個。
串行和并行:串行是多個任務(wù)按一定順序執(zhí)行矗钟,并行是多個任務(wù)同時執(zhí)行唆香;代碼是在分線程執(zhí)行,在主線程嘟列中刷新UI吨艇。
GCD:GCD核心是將任務(wù)放在分發(fā)隊列中去執(zhí)行.分發(fā)隊列分為兩種:
串行隊列:SerialQueue.如果將任務(wù)放在一個串行隊列中.那么任務(wù)會順序執(zhí)行.遵循FIFO,可以實現(xiàn)線程同步.但是當(dāng)有多個serialQueue時,串行隊列和串行隊列中的任務(wù)可以實現(xiàn)并發(fā)執(zhí)行.串行隊列兩種:
系統(tǒng)自帶的 : 主隊列;當(dāng)把任務(wù)放在主隊列中時,任務(wù)會按照順序在主隊列中執(zhí)行.
dispatch_queue_t queue = dispatch_get_main_queue();
自己創(chuàng)建的 : 自己創(chuàng)建的隊列中的任務(wù)會在其他線程中順序執(zhí)行.
dispatch_queue_t queue = dispatch_queue_create(“com.xxw.serialQueue", DISPATCH_QUEUE_SERIAL);
并行隊列分為兩種:
(1).系統(tǒng)自帶的: 使用系統(tǒng)提供好的globalQueue會開辟子線程來執(zhí)行任務(wù),任務(wù)的執(zhí)行是并發(fā)執(zhí)行的.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
(2).自己創(chuàng)建的: 一般情況下,不回你自己創(chuàng)建并行隊列,因為系統(tǒng)提供好的globalQueue(在子線程)可以滿足需求.
dispatch_queue_t queue = dispatch_queue_create("com.fy.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
- GCD其他用法
(1).使用dispatch_after 延遲特定的時間去做某事
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ });
(2).dispatch_sync函數(shù)會阻塞當(dāng)前線程,去對應(yīng)的隊列中去執(zhí)行block中的任務(wù),當(dāng)任務(wù),執(zhí)行完之后才會回到原來的線程中dispatch_sync(dispatch_get_main_queue(), ^{ });
(3)dispatch_apply重復(fù)執(zhí)行dispatch_apply(arr.count, dispatch_queue_create("com.fy.apply", DISPATCH_QUEUE_SERIAL), ^(size_t i) {});
(4).barrier 函數(shù)在使用的時候隊列必須是自己創(chuàng)建的的并行隊列,否則barrier順序起不到作用;
dispatch_queue_t queue = dispatch_queue_create("com.fy.barrier", DISPATCH_QUEUE_CONCURRENT);
dispatch_barrier_async(queue, ^{
dispatch_async(queue, ^{
});
dispatch_async(queue, ^{
});});
(5).使用group_notify函數(shù)/ 只有當(dāng)小組內(nèi)所有任務(wù)完成之后,才會執(zhí)行g(shù)roup_notify里面的內(nèi)容(PS:小組內(nèi)最起碼要有一組任務(wù));
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_main_queue(), ^{ });
dispatch_group_notify(group, dispatch_get_main_queue(), ^{ });
dispatch_group_async(group, dispatch_get_main_queue(), ^{ });
(6).dispatch_once_t``` static dispatch_once_t oneToken;dispatch_once(&oneToken, ^{ NSLog(@"你就是我的唯一");});
15:如何使用隊列來避免資源搶奪躬它?
(1)加各種鎖參考文章:鏈接
16:數(shù)據(jù)持久化的幾個方案(fmdb用沒用過)?
數(shù)據(jù)存儲的核心都是寫文件。
屬性列表:只有NSString东涡、NSArray冯吓、NSDictionary、NSData可writeToFile疮跑;存儲依舊是plist文件组贺。plist文件可以存儲的7中數(shù)據(jù)類型:array、dictionary祖娘、string锣披、bool、data、date雹仿、number。
對象序列化(對象歸檔):對象序列化通過序列化的形式整以,鍵值關(guān)系存儲到本地胧辽,轉(zhuǎn)化成二進(jìn)制流。通過runtime實現(xiàn)自動化歸檔/解檔公黑。實現(xiàn)NSCoding協(xié)議必須實現(xiàn)的兩個方法:1.編碼(對象序列化):把不能直接存儲到plist文件中得到數(shù)據(jù)邑商,轉(zhuǎn)化為二進(jìn)制數(shù)據(jù),NSData凡蚜,可以存儲到本地人断;2.解碼(對象反序列化):把二進(jìn)制數(shù)據(jù)轉(zhuǎn)化為本來的類型。
SQLite 數(shù)據(jù)庫:大量有規(guī)律的數(shù)據(jù)使用數(shù)據(jù)庫朝蜘。
CoreData :通過管理對象進(jìn)行增恶迈、刪、查谱醇、改操作的暇仲。它不是一個數(shù)據(jù)庫,不僅可以使用SQLite數(shù)據(jù)庫來保持?jǐn)?shù)據(jù)副渴,也可以使用其他的方式來存儲數(shù)據(jù)奈附。如:XML。
17:說一下AppDelegate的幾個方法煮剧?從后臺到前臺調(diào)用了哪些方法斥滤?第一次啟動調(diào)用了哪些方法?從前臺到后臺調(diào)用了哪些方法勉盅?
參考文章鏈接
(1)從后臺到前臺調(diào)用了哪些方法:
從后臺到前臺
- (void)applicationWillEnterForeground:(UIApplication *)application { 被稱為從后臺到活動狀態(tài)的轉(zhuǎn)換的一部分; 在這里你可以撤消許多在輸入背景所做的更改佑颇。 }
從后他到前臺時會調(diào)用 應(yīng)用程序?qū)⒁M(jìn)入活躍狀態(tài)
- (void)applicationDidBecomeActive:(UIApplication *)application { 在應(yīng)用程序處于非活動狀態(tài)時,重新啟動已暫停(或尚未啟動)的任何任務(wù)菇篡。 如果應(yīng)用程序先前在后臺漩符,則可選擇刷新用戶界面。 }
從后臺到前臺時會調(diào)用 在這里可以設(shè)置允許后臺運行
- (void)applicationDidEnterBackground:(UIApplication *)application { 使用此方法釋放共享資源驱还,保存用戶數(shù)據(jù)嗜暴,使計時器無效,并存儲足夠的應(yīng)用程序狀態(tài)信息以將應(yīng)用程序恢復(fù)到其當(dāng)前狀態(tài)议蟆,以防以后終止闷沥。 如果您的應(yīng)用程序支持后臺執(zhí)行,則調(diào)用此方法咐容,而不是applicationWillTerminate:當(dāng)用戶退出時舆逃。 }
(2)第一次啟動調(diào)用了哪些方法:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
在應(yīng)用程序啟動后覆蓋自定義點。
launchOptions中的值:
1.用戶直接啟動,lauchOptions內(nèi)無數(shù)據(jù);
2.其他應(yīng)用程序通過openURL:啟動路狮,則UIApplicationLaunchOptionsURLKey對應(yīng)的對象為啟動URL(NSURL),
UIApplicationLaunchOptionsSourceApplicationKey對應(yīng)啟動的源應(yīng)用程序的bundle ID (NSString)虫啥;
3.本地通知啟動,則UIApplicationLaunchOptionsLocalNotificationKey對應(yīng)的是為啟動應(yīng)用程序的的本地通知對象(UILocalNotification)奄妨;
4.遠(yuǎn)程通知啟動涂籽,則UIApplicationLaunchOptionsRemoteNotificationKey對應(yīng)的是啟動應(yīng)用程序的的遠(yuǎn)程通知信息userInfo(NSDictionary);
5.其他鍵:
UIApplicationLaunchOptionsAnnotationKey userInfo包含帶注釋屬性列表的對象
UIApplicationLaunchOptionsLocationKey 應(yīng)用程序是響應(yīng)CoreLocation事件而啟動的
UIApplicationLaunchOptionsNewsstandDownloadsKey userInfo包含NKAssetDownload的NSArray
UIApplicationLaunchOptionsBluetoothCentralsKey userInfo包含CBCentralManager恢復(fù)標(biāo)識符的NSArray
UIApplicationLaunchOptionsBluetoothPeripheralsKey userInfo包含CBPeripheralManager恢復(fù)的NSArray
UIApplicationLaunchOptionsShortcutItemKey userInfo包含用于啟動應(yīng)用程序的UIApplicationShortcutItem砸抛。
鍵入選項字典傳遞給應(yīng)用程序:[will | didFinishLaunchingWithOptions和UIApplicationDidFinishLaunchingNotification的信息
UIApplicationLaunchOptionsUserActivityDictionaryKey 存在用戶活動時啟動選項中存在的子詞典
UIApplicationLaunchOptionsUserActivityTypeKey 鍵入活動類型的用戶活動字典
UIApplicationLaunchOptionsCloudKitShareMetadataKey 此鍵的存在表示應(yīng)用程序已啟動评雌,以便處理CloudKit共享邀請。 此鍵的值是共享元數(shù)據(jù)對象直焙。
return YES;
}
(3)從前臺到后臺調(diào)用了哪些方法:
將要從活躍到不活躍 如:前臺到后臺 切換應(yīng)用程序 在此期間景东,應(yīng)用程序不接收消息或事件,比如網(wǎng)絡(luò)電話奔誓。
- (void)applicationWillResignActive:(UIApplication *)application { 當(dāng)應(yīng)用程序即將從活動狀態(tài)遷移到非活動狀態(tài)時發(fā)送斤吐。 這可能發(fā)生在某些類型的臨時中斷(例如來電或SMS消息)時,或者當(dāng)用戶退出應(yīng)用程序并且開始轉(zhuǎn)換到后臺狀態(tài)時丝里。 使用此方法暫停正在進(jìn)行的任務(wù)曲初,禁用計時器,并使渲染回調(diào)無效杯聚。 游戲應(yīng)該使用這種方法暫停游戲臼婆。 }
18:NSCache優(yōu)于NSDictionary的幾點?
NSCache勝過NSDictionary之處在于
(1):當(dāng)系統(tǒng)資源將要耗盡時幌绍,它可以自動刪減緩存颁褂。如果采用普通的字典,那么就要自己編寫掛鉤傀广,在系統(tǒng)發(fā)出“低內(nèi)存”通知時手工刪減緩存颁独。
(2):NSCache并不會“拷貝”鍵,而是會“保留”它伪冰。此行為用NSDictionary也可以實現(xiàn)誓酒,然而需要編寫相當(dāng)復(fù)雜的代碼。NSCache對象不拷貝鍵的原因在于:很多時候贮聂,鍵都是不支持拷貝操作的對象來充當(dāng)?shù)目扛獭R虼耍琋SCache不會自動拷貝鍵吓懈,所以說歼冰,在鍵不支持拷貝操作的情況下,該類用起來比字典更方便耻警。
(3):NSCache是線程安全的隔嫡,而NSDictionary則絕對不具備此優(yōu)勢甸怕。
19:實現(xiàn)description方法能取到什么效果?
一般情況下腮恩,我們在使用NSLog 和 %@ 輸出某個對象時梢杭,就會調(diào)用這個對象的 description 方法,它的返回值就是 NSString 字符串類型秸滴,所以 description 默認(rèn)實現(xiàn)返回的格式是 <類名: 對象的內(nèi)存地址>.那么式曲,既然description方法的默認(rèn)實現(xiàn)是返回類名和對象的內(nèi)存地址,所以在必要情況下缸榛,我們需要重寫description方法以達(dá)到改變輸出結(jié)果目的,覆蓋description方法的默認(rèn)實現(xiàn)兰伤,重寫完description方法后.我們就可以得到我們想要的信息,真正用的到位的話内颗,調(diào)試起來會很方便,很省時間敦腔,提高效率的均澳。
20:objc使用什么機(jī)制管理對象內(nèi)存?
iOS中采用的是引用計數(shù)的機(jī)制來管理內(nèi)存符衔,如果一塊內(nèi)存區(qū)域的引用計數(shù)不為0找前,那么就說明有對象持或者是在使用這一塊內(nèi)存,如果引用計數(shù)為0的話那么說明這塊內(nèi)存沒有對象使用判族,可以被系統(tǒng)回收掉躺盛。iOS借助于引用計數(shù)的增減來輔助我們進(jìn)行內(nèi)存的申請和釋放.內(nèi)存管理的原則:
(1)、自己創(chuàng)建的對象形帮,自己可以持有(比如以alloc槽惫、new、copy辩撑、mutableCopy開頭的方法可以創(chuàng)建對象)界斜;
(2)、不是自己創(chuàng)建的對象也可以持有合冀,通過retain各薇;
(3)、自己持有的對象在不需要使用的時候要負(fù)責(zé)釋放君躺、釋放可以通過release或者是autorelease進(jìn)行釋放峭判,
(4)、不是自己持有的對象不能進(jìn)行釋放晰洒,比如便利構(gòu)造器得到的對象朝抖。
在內(nèi)存管理的過程中我們需要謹(jǐn)記的原則就是我們造成的引用計數(shù)的增加和我們造成的引用計數(shù)的減少要保持一致。在我們使用屬性的過程中谍珊,要注意不同的語義控制(assign治宣、retain急侥、copy)的setter方法實現(xiàn)的不同,對于retain和copy來說侮邀,他們的內(nèi)部實現(xiàn)都是先把舊值release和把新值retain坏怪。另外對于發(fā)送autorelease消息的對象會被加到最近的自動釋放池中,當(dāng)自動釋放池釋放的時候绊茧,會給里面的所有對象發(fā)送一次release消息铝宵。iOS5.0之后蘋果推出了ARC、ARC是編譯器的特性华畏,不是OC的語言特性鹏秋,是編譯器在靜態(tài)編譯的基礎(chǔ)上(command + shift + B),編譯器在合適的地方給我們加了retain亡笑、release侣夷、autorelease這些代碼,不用我們自己去手動寫這些代碼了仑乌。ARC中屬性的關(guān)鍵字是strong和weak百拓,其中strong和MRC下的retain作用相同,都是持有一個對象晰甚,weak和MRC下的assigin類型衙传,是一個弱引用,不持有一個對象厕九,但是weak只能修飾對象類型蓖捶,不能修飾基本類型,并且weak會在指向的對象被銷毀的時候指針自動置nil止剖。