技術(shù)
最近正在準(zhǔn)備換份工作, 看到網(wǎng)上有份題庫, 覺得不錯, 準(zhǔn)備整理下, 復(fù)習(xí)下所學(xué)知識, 為面試做足準(zhǔn)備, 下面是我整理了一上午的題庫答案, 希望能幫大家溫習(xí)下知識; 當(dāng)然如果同為找工作的朋友, 也希望你能找到份誠心的工作;之后的答案已附下方, 謝謝大家(__) 嘻嘻……
基礎(chǔ)
1. 為什么說Objective-C是一門動態(tài)的語言负间?
① 什么是動態(tài)語言红碑?
動態(tài)語言庇忌,是指程序在運行時可以改變其結(jié)構(gòu):新的函數(shù)可以被引進,已有的函數(shù)可以被刪除等在結(jié)構(gòu)上的變化怕敬。比如眾所周知的ECMAScript(JavaScript)便是一個動態(tài)語言置森。除此之外如Ruby、Python等也都屬于動態(tài)語言槽卫,而C、C++等語言則不屬于動態(tài)語言扒袖。
有三個名詞容易混淆:
Dynamic Programming Language (動態(tài)語言或動態(tài)編程語言)
Dynamically Typed Language (動態(tài)類型語言)
Statically Typed Language (靜態(tài)類型語言)
所謂的動態(tài)類型語言塞茅,意思就是類型的檢查是在運行時做的。
② 靜態(tài)類型
而靜態(tài)類型語言的類型判斷是在運行前判斷(如編譯階段)季率,比如C#野瘦、Java就是靜態(tài)類型語言,靜態(tài)類型語言為了達(dá)到多態(tài)會采取一些類型鑒別手段飒泻,如繼承鞭光、接口,而動態(tài)類型語言卻不需要泞遗,所以一般動態(tài)語言都會采用dynamic typing惰许,常出現(xiàn)于腳本語言中.需要明確說明一點,那就是史辙,是不是動態(tài)類型語言與這門語言是不是類型安全的完全不相干的汹买,不要將它們聯(lián)系在一起!
優(yōu)缺點:
靜態(tài)類型語言的主要優(yōu)點在于其結(jié)構(gòu)非常規(guī)范聊倔,便于調(diào)試卦睹,方便類型安全;缺點是為此需要寫更多的類型相關(guān)代碼方库,導(dǎo)致不便于閱讀、不清晰明了障斋。動態(tài)類型語言的優(yōu)點在于方便閱讀纵潦,不需要寫非常多的類型相關(guān)的代碼;缺點自然就是不方便調(diào)試垃环,命名不規(guī)范時會造成讀不懂邀层,不利于理解等。順便說一下遂庄,現(xiàn)在有這樣一種趨勢寥院,那就是合并動態(tài)類型與靜態(tài)類型在一種語言中,這樣可以在必要的時候取長補短涛目,Boo就是一個很好的試驗性例子秸谢。
③ Objective-C的動態(tài)運行性
objective-c語言是C語言的一個子類,所以O(shè)bjective-C是一個靜態(tài)語言霹肝,但是Objective-C的三大特性之一的多態(tài)性讓其擁有了動態(tài)性估蹄。
oc的動態(tài)性讓程序可以在運行時判斷其該有的行為,而不是像c等靜態(tài)語言一樣在編譯構(gòu)建時就確定下來沫换。它的動態(tài)性主要體現(xiàn)在一下三個方面:
1. 動態(tài)類型
如id類型臭蚁。實際上靜態(tài)類型因為其固定性和可預(yù)知性而使用得更加廣泛。靜態(tài)類型是強類型,而動態(tài)類型屬于弱類型垮兑。運行時決定接收者冷尉。
這里補充講一下強、弱類型:語言有無類型系枪、強類型和弱類型三種雀哨。無類型的不做任何檢查,甚至不區(qū)分指令和數(shù)據(jù)嗤无;弱類型的檢查很弱震束,僅能區(qū)分指令和數(shù)據(jù);強類型的嚴(yán)格在編譯期進行檢查当犯。強類型語言在沒有強制類型轉(zhuǎn)化前垢村,不允許兩種不同類型的變量相互操作
2. 動態(tài)綁定
讓代碼在運行時判斷需要調(diào)用什么方法,而不是在編譯時嚎卫。與其他面向?qū)ο笳Z言一樣嘉栓,方法調(diào)用和代碼并沒有在編譯時連接在一起,而是在消息發(fā)送時才進行連接拓诸。運行時決定調(diào)用哪個方法侵佃。
3. 動態(tài)載入
讓程序在運行時添加代碼模塊以及其他資源。用戶可以根據(jù)需要加載一些可執(zhí)行代碼和資源奠支,而不是在啟動時就加載所有組件馋辈。可執(zhí)行代碼中可以含有和程序運行時整合的新類倍谜。
對象是運行時類的一個實例迈螟。在類里聲明了的實例變量和方法,它的每個實例都在內(nèi)存中擁有同樣的實例變量尔崔,以及指向那些方法的指針答毫。在oc中對象永遠(yuǎn)是通過指針來引用的。
2.講一下MVC和MVVM季春,MVP洗搂?
MVC,MVP 和 MVVM 的圖示
3.為什么代理要用weak载弄?代理的delegate和dataSource有什么區(qū)別耘拇?block和代理的區(qū)別?
代理屬性都用weak或是assign修飾, 現(xiàn)整理下weak(assign)與strong(retain)修飾區(qū)別:
@property (nonatomic, weak) id<MainVCDelegate>delegate;
weak:指明該對象并不負(fù)責(zé)保持delegate這個對象,delegate這個對象的銷毀由外部控制
@property (nonatomic, strong) id<MainVCDelegate>delegate;
strong:該對象強引用delegate宇攻,外界不能銷毀delegate對象驼鞭,會導(dǎo)致循環(huán)引用(Retain MainVC)
Datasource和Delegate兩者的區(qū)別:
Datasource 是在告訴使用者之前的view中都有什么東西,有什么屬性啊尺碰,屬性的值都是多少挣棕,是只關(guān)于數(shù)據(jù)的東西译隘。
Delegate 是在告訴使用者之前的view有什么方法可以供我調(diào)用。
一個是數(shù)據(jù)洛心,一個是操作.
block和代理的區(qū)別:
首先兩者作用是一樣的固耘,都是進行單一回調(diào)。不同的是词身,delegate是個對象厅目,然后用過一個對象自己調(diào)用代理協(xié)議函數(shù)來完成整個流程。block是傳遞一個函數(shù)指針法严,利用函數(shù)指針執(zhí)行來進行回調(diào)损敷。還有在內(nèi)存管理上需要注意,delegate不需要保存引用深啤。block對引用數(shù)據(jù)有copy的處理拗馒。
3. 屬性的實質(zhì)是什么?包括哪幾個部分溯街?屬性默認(rèn)的關(guān)鍵字都有哪些诱桂?@dynamic關(guān)鍵字和@synthesize關(guān)鍵字是用來做什么的?
屬性的組成: @property = ivar + getter + setter;
實例變量+get方法+set方法,也就是說使用@property 系統(tǒng)會自動生成setter和getter方法;
在ARC下,默認(rèn)的系統(tǒng)關(guān)鍵字如下:
基本數(shù)據(jù): atomic,readwrite,assign
普通的OC對象: atomic,readwrite,strong
對于經(jīng)常使用assign,weak,strong,copy,nonatomic,atomic,readonly等關(guān)鍵字呈昔,下面我們列個表格去歸納一下屬性關(guān)鍵字具體作用:
@synthesize和@dynamic區(qū)別, 在聲明property屬性后挥等,有2種實現(xiàn)選擇:
@synthesize
編譯器期間,讓編譯器自動生成getter/setter方法堤尾。
當(dāng)有自定義的存或取方法時肝劲,自定義會屏蔽自動生成該方法
@dynamic
告訴編譯器,不自動生成getter/setter方法郭宝,避免編譯期間產(chǎn)生警告
然后由自己實現(xiàn)存取方法
或存取方法在運行時動態(tài)創(chuàng)建綁定:主要使用在CoreData的實現(xiàn)NSManagedObject子類時使用辞槐,由Core Data框架在程序運行的時動態(tài)生成子類屬性
iOS_研究(3)_@property 屬性的本質(zhì)是什么?
5.屬性的默認(rèn)關(guān)鍵字是什么?
對于基本數(shù)據(jù)類型默認(rèn)關(guān)鍵字是
atomic,readwrite,assign
對于普通的OC對象
atomic,readwrite,strong
6.NSString為什么要用copy關(guān)鍵字剩蟀,如果用strong會有什么問題?(注意:這里沒有說用strong就一定不行切威。使用copy和strong是看情況而定的)
怎么用 copy 關(guān)鍵字育特?
7.如何令自己所寫的對象具有拷貝功能?
如何讓自己的類用 copy 修飾符?如何重寫帶 copy 關(guān)鍵字的 setter?
8.可變集合類 和 不可變集合類的 copy 和 mutablecopy有什么區(qū)別先朦?如果是集合是內(nèi)容復(fù)制的話缰冤,集合里面的元素也是內(nèi)容復(fù)制么?
首先我們要先明白一個概念喳魏,什么是淺復(fù)制棉浸,單層深復(fù)制,完全復(fù)制(每一層都深復(fù)制)
淺復(fù)制也就是所說的指針復(fù)制刺彩,并沒有進行對象復(fù)制;
單層深復(fù)制迷郑,也就是我們經(jīng)常說的深復(fù)制枝恋,我這里說的單層深復(fù)制是對于集合類所說的(即NSArray,NSDictionary,NSSet),單層深復(fù)制指的是只復(fù)制了該集合類的最外層嗡害,里邊的元素沒有復(fù)制焚碌,(即這兩個集合類的地址不一樣,但是兩個集合里所存儲的元素的地址是一樣的);
完全復(fù)制霸妹,指的是完全復(fù)制整個集合類十电,也就是說兩個集合地址不一樣,里邊所存儲的元素地址也不一樣;
明白了這三個概念之后叹螟,我們就來說一下他們的區(qū)別所在:
- 非集合類(NSString鹃骂,NSNumber)
[immutableObject copy] //淺復(fù)制
[immutableObject mutableCopy] //深復(fù)制
[mutableObject copy] //深復(fù)制
[mutableObject mutableCopy] //深復(fù)制
結(jié)論:不可變進行copy是淺復(fù)制,mutableCopy是深復(fù)制罢绽,可變的copy畏线,mutableCopy都是深復(fù)制
- 集合類(NSArray,NSDictionary, NSSet):
[immutableObject copy] //淺復(fù)制
[immutableObject mutableCopy] //單層深復(fù)制
[mutableObject copy] //單層深復(fù)制
[mutableObject mutableCopy] //單層深復(fù)制
結(jié)論:不可變進行copy是淺復(fù)制有缆,mutableCopy是單層深復(fù)制象踊,可變的copy,mutableCopy都是單層深復(fù)制
那么如何實現(xiàn)多層復(fù)制呢棚壁?
以NSArray舉例說明
NSArray *copyArray = [[NSArray alloc] initWithArray:array copyItems:YES]; // 完全復(fù)制
需要特別注意的是
以上我們所說的兩種情況默認(rèn)都實現(xiàn)了NSCopying和NSMutableCopying協(xié)議
對于自定義繼承自NSObject的類
- copy需要實現(xiàn)NSCopying協(xié)議杯矩,然后實現(xiàn)以下方法,否則copy會crash
-(id)copyWithZone:(NSZone *)zone {
CopyObject *copy = [[[self class] alloc] init];
copy.name = self.name;
copy.mobile = self.mobile;
copy.company = self.company;
copy.descInfo = self.descInfo;
return copy;
}
- mutableCopy時袖外,需要實現(xiàn)NSMutableCopying協(xié)議史隆,否則mutableCopy會crash
-(id)mutableCopyWithZone:(NSZone *)zone {
MutableCopyObject *mutableCopy = [[[self class] alloc] init];
mutableCopy.name = self.name;
mutableCopy.mobile = self.mobile;
mutableCopy.company = self.company;
mutableCopy.descInfo = self.descInfo;
return mutableCopy;
}
9.為什么IBOutlet修飾的UIView也適用weak關(guān)鍵字?
因為當(dāng)我們將控件拖到Storyboard上曼验,相當(dāng)于新創(chuàng)建了一個對象泌射,而這個對象是加到視圖控制器的view上,view有一個subViews屬性鬓照,這個屬性是一個數(shù)組熔酷,里面是這個view的所有子view,而我們加的控件就位于這個數(shù)組中豺裆,那么說明拒秘,實際上我們的控件對象是屬于view的臭猜,也就是說view對加到它上面的控件是強引用躺酒。當(dāng)我們使用Outlet屬性的時候,我們是在viewController里面使用蔑歌,而這個Outlet屬性是有view來進行強引用的羹应,我們在viewController里面僅僅是對其使用,并沒有必要擁有它次屠,所以是weak的园匹。
如果將weak改為strong雳刺,也是沒有問題的,并不會造成強引用循環(huán)偎肃。當(dāng)viewController的指針指向其他對象或者為nil煞烫,這個viewController銷毀,那么對控件就少了一個強引用指針累颂。然后它的view也隨之銷毀滞详,那么subViews也不存在了,那么控件就又少了一個強引用指針紊馏,如果沒有其他強引用料饥,那么這個控件也會隨之銷毀。
不過朱监,既然沒有必將Outlet屬性設(shè)置為strong岸啡,那么用weak就好了;
一個控件可以在viewController里面有多個Outlet屬性,就相當(dāng)于一個對象赫编,可以有多個指針指向它(多個引用)巡蘸。
但是一個Outlet屬性只能對應(yīng)一個控件,也就是說擂送,如果有button1和button2悦荒,button1在viewController里面有一個名為button的Outlet屬性,此時button指向button1嘹吨,但是如果用button2給button重新賦值搬味,那么此時button指向button2。也就是說蟀拷,后來的覆蓋原來的碰纬。
一個控件可以在viewController里面觸發(fā)多個IBAction。比如有一個button控件问芬,在viewController里面有幾個方法悦析,那么點擊button,會觸發(fā)所有的這些方法此衅。
如果我有多個控件强戴,比如button1,button2,button3,它們也可以同時綁定一個buttonClick方法炕柔,無論點擊button1,button2還是button3酌泰,都會觸發(fā)這個buttonClick方法媒佣。
上面說了匕累,button1,button2,button3有可能都觸發(fā)buttonClick方法,如果想在buttonClick方法里面區(qū)分到底是哪個button觸發(fā)的可能有好幾種做法默伍。
可以給這三個button各設(shè)置一個Outlet屬性欢嘿,然后在buttonClick里面判斷sender和哪個Outlet屬性是同一對象衰琐,這樣就可以區(qū)分了。但是很明顯炼蹦,這樣并不合理羡宙,因為創(chuàng)建的三個屬性有些浪費。
我們可以給三個button各加一個tag掐隐,在buttonClick里面通過switch(或者if...)判斷狗热,sender的tag和給各個button加上的tag是否一致,如果一致則為同一對象虑省。
要慎用tag匿刮。因為view有一個viewWithTag:方法,可以在view的子view里面找到和我們傳入的tag相同的view探颈,這樣哪怕不給這個控件創(chuàng)建Outlet屬性熟丸,也可以通過tag找到這個對象。但是很明顯伪节,這個方法要遍歷子view光羞,比較每個子view的tag,這樣效率并不高怀大,所以盡量要避免這種情況纱兑。
10.nonatomic和atomic的區(qū)別?atomic是絕對的線程安全么叉寂?為什么萍启?如果不是,那應(yīng)該如何實現(xiàn)屏鳍?
在默認(rèn)情況下勘纯,由編譯器所合成的方法會通過鎖定機制確保其原子性(atomicity)。如果屬性具備nonatomic特質(zhì)钓瞭,則不需要同步鎖驳遵。
下面說一下atomic與nonatomic的區(qū)別:
具備atomic特質(zhì)的獲取方法會通過鎖定機制來確保其操作的原子性。也就是說山涡,如果兩個線程同時讀取一個屬性堤结,那么不論何時,總能看到有效的屬性值鸭丛。
如果不加鎖的話(或者說使用nonatomic語義)竞穷,那么當(dāng)其中一個線程正在改寫某屬性值的時候,另外一個線程也許會突然闖入鳞溉,把尚未修改好的屬性值讀取出來瘾带。發(fā)證這種情況時,線程讀取道德屬性值肯能不對熟菲。
一般iOS程序中看政,所有屬性都聲明為nonatomic朴恳。這樣做的原因是:
在iOS中使用同步鎖的開銷比較大, 這會帶來性能問題允蚣。一般情況下并不要求屬性必須是“原子的”于颖,因為這并不能保證“線程安全”(thread safety),若要實現(xiàn)“線程安全”的操作嚷兔,還需采用更為深層的鎖定機制才行森渐。
例如:一個線程在連續(xù)多次讀取某個屬性值的過程中有別的線程在同時改寫該值,那么即便將屬性聲明為atomic冒晰,也還是會讀取到不同的屬性值章母。
因此,iOS程序一般都會使用nonatomic屬性翩剪。但是在Mac OS X程序時乳怎, 使用atomic屬性通常都不會有性能瓶頸;
然而atomic一定是線程安全的么,回答是NO :
nonatomic的內(nèi)存管理語義是非原子性的前弯,非原子性的操作本來就是線程不安全蚪缀,而atomic的操作是原子性的,但并不意味著他就是線程安全的恕出,它會增加正確的幾率询枚,能夠更好的避免線程錯誤,但仍舊是不安全的浙巫。
為了說atomic與nonatomic的本質(zhì)區(qū)別其實也就是在setter方法上的操作不同:
nonatomic的實現(xiàn):
- (void)setCurrentImage:(UIImage *)currentImage
{
if (_currentImage != currentImage) {
[_currentImage release];
_currentImage = [currentImage retain];
// do something
}
}
- (UIImage *)currentImage
{
return _currentImage;
}
atomic的實現(xiàn):
- (void)setCurrentImage:(UIImage *)currentImage
{
@synchronized(self) {
if (_currentImage != currentImage) {
[_currentImage release];
_currentImage = [currentImage retain];
// do something
}
}
}
- (UIImage *)currentImage
{
@synchronized(self) {
return _currentImage;
}
}
Using the @synchronized Directive
The @synchronized directive is a convenient way to create mutex locks on the fly in Objective-C code. The @synchronized directive does what any other mutex lock would do—it prevents different threads from acquiring the same lock at the same time. In this case, however, you do not have to create the mutex or lock object directly. Instead, you simply use any Objective-C object as a lock token, as shown in the following example:
- (void)myMethod:(id)anObj
{
@synchronized(anObj)
{
// Everything between the braces is protected by the @synchronized directive.
}
}
The object passed to the @synchronized directive is a unique identifier used to distinguish the protected block. If you execute the preceding method in two different threads, passing a different object for the anObj parameter on each thread, each would take its lock and continue processing without being blocked by the other. If you pass the same object in both cases, however, one of the threads would acquire the lock first and the other would block until the first thread completed the critical section.
As a precautionary measure, the @synchronized block implicitly adds an exception handler to the protected code. This handler automatically releases the mutex in the event that an exception is thrown. This means that in order to use the @synchronized directive, you must also enable Objective-C exception handling in your code. If you do not want the additional overhead caused by the implicit exception handler, you should consider using the lock classes.
For more information about the @synchronized directive, see The Objective-C Programming Language.
當(dāng)使用atomic時金蜀,雖然對屬性的讀和寫是原子性的,但是仍然可能出現(xiàn)線程錯誤:當(dāng)線程A進行寫操作的畴,這時其他線程的讀或者寫操作會因為等該操作而等待渊抄。當(dāng)A線程的寫操作結(jié)束后,B線程進行寫操作丧裁,所有這些不同線程上的操作都將依次順序執(zhí)行——也就是說护桦,如果一個線程正在執(zhí)行 getter/setter,其他線程就得等待煎娇。如果有線程C在A線程讀操作之前release了該屬性二庵,那么還會導(dǎo)致程序崩潰。所以僅僅使用atomic并不會使得線程安全缓呛,我們還要為線程添加lock來確保線程的安全催享。
更準(zhǔn)確的說應(yīng)該是讀寫安全,但并不是線程安全的哟绊,因為別的線程還能進行讀寫之外的其他操作因妙。線程安全需要開發(fā)者自己來保證。
其實無論是否是原子性的只是針對于getter和setter而言,比如用atomic去操作一個NSMutableArray 兰迫,如果一個線程循環(huán)讀數(shù)據(jù),一個線程循環(huán)寫數(shù)據(jù)炬称,肯定會產(chǎn)生內(nèi)存問題汁果,這個就跟getter和setter就木有關(guān)系了。
11.UICollectionView自定義layout如何實現(xiàn)玲躯?
關(guān)于自定義UICollectionViewLayout的一點個人理解
12.用StoryBoard開發(fā)界面有什么弊端据德?如何避免?
難以維護
Storyboard在某些角度上跷车,是難以維護的棘利。我所遇到過的實際情況是,公司一個項目的2.0版本朽缴,設(shè)計師希望替換原有字體善玫。然而原來項目的每一個Label都是采用Storyboard來定義字體的,因此替換新字體需要在Storyboard中更改每一個Label密强。
幸虧我們知道Storyboard的源文件是XML茅郎,最終寫了一個讀取-解析-替換腳本來搞定這件事。性能瓶頸
當(dāng)項目達(dá)到一定的規(guī)模或渤,即使是高性能的MacBook Pro,在打開Storyboard是也會有3-5秒的讀取時間系冗。無論是只有幾個Scene的小東西,還是幾十個Scene的龐然大物薪鹦,都無法避免掌敬。Scene越多的文件,打開速度越慢(從另一個方面說明了分割大故事板的重要性)池磁。
讓人沮喪的是奔害,這個造成卡頓的項目規(guī)模并不是太難達(dá)到。
我猜想是由于每一次打開都需要進行I/O操作造成的地熄,Apple對這一塊的緩存優(yōu)化沒有做到位舀武。可能是由于Storyboard占用了太多內(nèi)存离斩,難以在內(nèi)存中進行緩存银舱。Whatever,這個問題總是讓人困擾的。
然而需要指出的是跛梗,采用Storyboard開發(fā)或采用純代碼開發(fā)的App寻馏,在真機的運行效率上,并沒有太大的區(qū)別核偿。錯誤定位困難
Storyboard的初學(xué)者應(yīng)該對此深有體會诚欠。排除BAD_EXCUSE錯誤不說,單單是有提示的錯誤,就足以讓人在代碼和Storyboard之間來回摸索轰绵,卻無法找到解決方案粉寞。
一個典型的例子是,在代碼中刪除了IBOUTLET屬性或者IBAction方法左腔,但是卻忘了在Storyboard中刪除對應(yīng)的連接唧垦,運行后crash。然而控制臺只會輸出一些模糊其詞的錯誤描述液样。
*** Terminating app due to uncaught exception 'NSUnknownKeyException',
reason: '[ setValue:forUndefinedKey:]:
this class is not key value coding-compliant for the key drawButton.'
最后
一方面是其提供的便利振亮,另一方面是Apple對Storyboard的大力支持。這一點宏觀上看鞭莽,可以在以往對Storyboard的改進和增強上看出坊秸,微觀上看,幾乎所有iOS 8之后的simple code都或多或少采用了Storyboard作為界面開發(fā)工具;
那改如何避免這些弊端呢, 參考以下文章:
iOS項目開發(fā)實戰(zhàn)——storyboard設(shè)置界面技巧與注意事項
13.進程和線程的區(qū)別澎怒?同步異步的區(qū)別褒搔?并行和并發(fā)的區(qū)別?
進程和線程:
進程中所包含的一個或多個執(zhí)行單元稱為線程(thread)喷面。比如一個應(yīng)用程序就是一個進程, 而它又包含了多個線程;主要差別在于它們是不同的操作系統(tǒng)資源管理方式站超。進程有獨立的地址空間,一個進程崩潰后乖酬,在保護模式下不會對其它進程產(chǎn)生影響涵卵,而線程只是一個進程中的不同執(zhí)行路徑宣吱。線程有自己的堆棧和局部變量磷蛹,但線程之間沒有單獨的地址空間疚脐,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程序健壯县昂,但在進程切換時肮柜,耗費資源較大,效率要差一些倒彰。但對于一些要求同時進行并且又要共享某些變量的并發(fā)操作审洞,只能用線程,不能用進程;
同步和異步:
在進行網(wǎng)絡(luò)編程時待讳,我們通常會看到同步芒澜、異步、阻塞创淡、非阻塞四種調(diào)用方式以及他們的組合痴晦。
其中同步方式、異步方式主要是由客戶端(client)控制的琳彩,具體如下:
同步(Sync)
所謂同步誊酌,就是發(fā)出一個功能調(diào)用時部凑,在沒有得到結(jié)果之前,該調(diào)用就不返回或繼續(xù)執(zhí)行后續(xù)操作碧浊。
根據(jù)這個定義涂邀,Java中所有方法都是同步調(diào)用,應(yīng)為必須要等到結(jié)果后才會繼續(xù)執(zhí)行箱锐。我們在說同步比勉、異步的時候,一般而言是特指那些需要其他端協(xié)作或者需要一定時間完成的任務(wù)瑞躺。
簡單來說,同步就是必須一件一件事做兴想,等前一件做完了才能做下一件事幢哨。
例如:B/S模式中的表單提交,具體過程是:客戶端提交請求->等待服務(wù)器處理->處理完畢返回嫂便,在這個過程中客戶端瀏覽器不能做其他事捞镰。
異步(Async)
異步與同步相對,當(dāng)一個異步過程調(diào)用發(fā)出后毙替,調(diào)用者在沒有得到結(jié)果之前岸售,就可以繼續(xù)執(zhí)行后續(xù)操作。當(dāng)這個調(diào)用完成后厂画,一般通過狀態(tài)凸丸、通知和回調(diào)來通知調(diào)用者。對于異步調(diào)用袱院,調(diào)用的返回并不受調(diào)用者控制屎慢。
總結(jié)來說,同步和異步的區(qū)別:請求發(fā)出后忽洛,是否需要等待結(jié)果腻惠,才能繼續(xù)執(zhí)行其他操作。
并行(parallellism)和并發(fā)(concurrency)的區(qū)別:
并行是指兩個或者多個事件在同一時刻發(fā)生欲虚;而并發(fā)是指兩個或多個事件在同一時間間隔發(fā)生集灌。
并行,是每個cpu運行一個程序;
并發(fā)复哆,是在同一個cpu上同時(不是真正的同時欣喧,而是看來是同時,因為cpu要在多個程序間切換)運行多個程序;
并發(fā)和并行的區(qū)別
14.線程間通信梯找?
- 使用全局變量主要由于多個線程可能更改全局變量续誉,因此全局變量最好聲明為violate
- 使用消息實現(xiàn)通信在Windows程序設(shè)計中,每一個線程都可以擁有自己的消息隊列(UI線程默認(rèn)自帶消息隊列和消息循環(huán)初肉,工作線程需要手動實現(xiàn)消息循環(huán))酷鸦,因此可以采用消息進行線程間通信sendMessage,postMessage。
1)定義消息#define WM_THREAD_SENDMSG=WM_USER+20;
2)添加消息函數(shù)聲明afx_msg int OnTSendmsg();
3)添加消息映射ON_MESSAGE(WM_THREAD_SENDMSG,OnTSM)
4)添加OnTSM()的實現(xiàn)函數(shù);
5)在線程函數(shù)中添加PostMessage消息Post函數(shù)
- 使用事件CEvent類實現(xiàn)線程間通信
Event對象有兩種狀態(tài):有信號和無信號臼隔,線程可以監(jiān)視處于有信號狀態(tài)的事件嘹裂,以便在適當(dāng)?shù)臅r候執(zhí)行對事件的操作。
1)創(chuàng)建一個CEvent類的對象:CEvent threadStart;它默認(rèn)處在未通信狀態(tài)摔握;
2)threadStart.SetEvent();使其處于通信狀態(tài)寄狼;
3)調(diào)用WaitForSingleObject()來監(jiān)視CEvent對象
15.GCD的一些常用的函數(shù)氨淌?(group泊愧,barrier,信號量盛正,線程同步)
- dispatch_group
- dispatch_barrier
- dispatch_semaphore(信號量)
附:
iOS GCD 線程同步方法
16.如何使用隊列來避免資源搶奪删咱?
ios多線程——鎖(解決多線程搶奪同一塊資源的問題)
17.數(shù)據(jù)持久化的幾個方案(fmdb用沒用過)
- plist文件(屬性列表)
- preference(偏好設(shè)置)
- NSKeyedArchiver(歸檔)
- SQLite 3
- CoreData
iOS中幾種數(shù)據(jù)持久化方案
18.說一下AppDelegate的幾個方法?從后臺到前臺調(diào)用了哪些方法豪筝?第一次啟動調(diào)用了哪些方法痰滋?從前臺到后臺調(diào)用了哪些方法?
1. – (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions NS_AVAILABLE_IOS(3_0);
當(dāng)應(yīng)用程序啟動時(不包括已在后臺的情況下轉(zhuǎn)到前臺)续崖,調(diào)用此回調(diào)敲街。launchOptions是啟動參數(shù),假如用戶通過點擊push通知啟動的應(yīng)用严望,這個參數(shù)里會存儲一些push通知的信息多艇。
2. – (void)applicationDidBecomeActive:(UIApplication *)application;
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
當(dāng)應(yīng)用程序全新啟動,或者在后臺轉(zhuǎn)到前臺像吻,完全激活時墩蔓,都會調(diào)用這個方法。如果應(yīng)用程序是以前運行在后臺萧豆,這時可以選擇刷新用戶界面奸披。
3. – (void)applicationDidEnterBackground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
當(dāng)用戶從前臺狀態(tài)轉(zhuǎn)入后臺時,調(diào)用此方法涮雷。使用此方法來釋放資源共享阵面,保存用戶數(shù)據(jù),無效計時器洪鸭,并儲存足夠的應(yīng)用程序狀態(tài)信息的情況下被終止后样刷,將應(yīng)用 程序恢復(fù)到目前的狀態(tài)。如果您的應(yīng)用程序支持后臺運行览爵,這種方法被調(diào)用置鼻,否則調(diào)用applicationWillTerminate:用戶退出。
4. – (void)applicationWillEnterForeground:(UIApplication *)application NS_AVAILABLE_IOS(4_0);
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
當(dāng)應(yīng)用在后臺狀態(tài)蜓竹,將要進行動前臺運行狀態(tài)時箕母,會調(diào)用此方法储藐。
如果應(yīng)用不在后臺狀態(tài),而是直接啟動嘶是,則不會回調(diào)此方法钙勃。
從后臺到前臺2, 4; 第一次啟動1, 2; 從前臺到后臺3;
19.NSCache優(yōu)于NSDictionary的幾點?
NSCache勝過NSDictionary之處在于聂喇,當(dāng)系統(tǒng)資源將要耗盡時辖源,它可以自動刪減緩存。如果采用普通的字典希太,那么就要自己編寫掛鉤克饶,在系統(tǒng)發(fā)出“低內(nèi)存”通知時手工刪減緩存。
NSCache并不會“拷貝”鍵誊辉,而是會“保留”它矾湃。此行為用NSDictionary也可以實現(xiàn),然而需要編寫相當(dāng)復(fù)雜的代碼芥映。NSCache對象不拷貝鍵的原因在于:很多時候洲尊,鍵都是不支持拷貝操作的對象來充當(dāng)?shù)脑恫颉R虼四纹琋SCache不會自動拷貝鍵,所以說躯护,在鍵不支持拷貝操作的情況下惊来,該類用起來比字典更方便。另外棺滞,NSCache是線程安全的裁蚁,而NSDictionary則絕對不具備此優(yōu)勢。
20.知不知道Designated Initializer继准?使用它的時候有什么需要注意的問題枉证?
iOS: 聊聊 Designated Initializer(指定初始化函數(shù))
正確編寫Designated Initializer的幾個原則
21.實現(xiàn)description方法能取到什么效果?
一般情況下移必,我們在使用NSLog 和 %@ 輸出某個對象時室谚,就會調(diào)用這個對象的 description 方法,它的返回值就是 NSString 字符串類型崔泵,所以 description 默認(rèn)實現(xiàn)返回的格式是 <類名: 對象的內(nèi)存地址>
如圖:
以上輸出實現(xiàn)的具體步驟為:
①調(diào)用對象p的-description方法
②拿到-description方法的返回值(NSString*)顯示到屏幕上
③-description方法默認(rèn)返回的是“類名+內(nèi)存地址”
那么秒赤,既然description方法的默認(rèn)實現(xiàn)是返回類名和對象的內(nèi)存地址,所以在必要情況下憎瘸,我們需要重寫description方法以達(dá)到改變輸出結(jié)果目的入篮,覆蓋description方法的默認(rèn)實現(xiàn),比如重寫上述代碼 Person 類的 description方法幌甘,返回_age和_name成員變量的值:
重寫完description方法后潮售,再調(diào)用NSLog(@”%@”,p)時輸出結(jié)果不再是<類名: 內(nèi)存地址>痊项,而是返回的字符串:
22.objc使用什么機制管理對象內(nèi)存?
- MRC(manual retain-release)手動內(nèi)存管理
- ARC(automatic reference counting)自動引用計數(shù)
- Garbage collection (垃圾回收)饲做。但是iOS不支持垃圾回收, ARC作為LLVM3.0編譯器的一項特性, 在iOS5.0 (Xcode4) 版本后推出的线婚。
- ARC的判斷準(zhǔn)則, 只要沒有強指針指向?qū)ο? 對象就會被釋放.
iOS開發(fā)系列—Objective-C之內(nèi)存管理
附:
2017年5月iOS招人心得答案總結(jié)(基礎(chǔ)篇)
2017年5月iOS招人心得答案總結(jié)(中級篇)
2017年5月iOS招人心得答案總結(jié)(高級篇)