Objective-C是一門動(dòng)態(tài)的語言
動(dòng)態(tài)語言,是指程序在運(yùn)行時(shí)可以改變其結(jié)構(gòu):新的函數(shù)可以被引進(jìn),已有的函數(shù)可以被刪除等在結(jié)構(gòu)上的變化指蚜。比如眾所周知的ECMAScript(JavaScript)便是一個(gè)動(dòng)態(tài)語言。除此之外如Ruby涨椒、Python等也都屬于動(dòng)態(tài)語言摊鸡,而C、C++等語言則不屬于動(dòng)態(tài)語言蚕冬。
有三個(gè)名詞容易混淆:DynamicProgrammingLanguage(動(dòng)態(tài)語言或動(dòng)態(tài)編程語言)? ? ? ? Dynamically TypedLanguage(動(dòng)態(tài)類型語言)? ? ? ? Statically TypedLanguage(靜態(tài)類型語言)
所謂的動(dòng)態(tài)類型語言免猾,意思就是類型的檢查是在運(yùn)行時(shí)做的。
而靜態(tài)類型語言的類型判斷是在運(yùn)行前判斷(如編譯階段)囤热,比如C#猎提、Java就是靜態(tài)類型語言,靜態(tài)類型語言為了達(dá)到多態(tài)會(huì)采取一些類型鑒別手段旁蔼,如繼承锨苏、接口,而動(dòng)態(tài)類型語言卻不需要棺聊,所以一般動(dòng)態(tài)語言都會(huì)采用dynamic typing伞租,常出現(xiàn)于腳本語言中.需要明確說明一點(diǎn),那就是躺屁,是不是動(dòng)態(tài)類型語言與這門語言是不是類型安全的完全不相干的肯夏,不要將它們聯(lián)系在一起!
優(yōu)缺點(diǎn):
靜態(tài)類型語言的主要優(yōu)點(diǎn)在于其結(jié)構(gòu)非常規(guī)范犀暑,便于調(diào)試,方便類型安全烁兰;缺點(diǎn)是為此需要寫更多的類型相關(guān)代碼耐亏,導(dǎo)致不便于閱讀、不清晰明了沪斟。動(dòng)態(tài)類型語言的優(yōu)點(diǎn)在于方便閱讀广辰,不需要寫非常多的類型相關(guān)的代碼暇矫;缺點(diǎn)自然就是不方便調(diào)試,命名不規(guī)范時(shí)會(huì)造成讀不懂择吊,不利于理解等李根。順便說一下,現(xiàn)在有這樣一種趨勢(shì)几睛,那就是合并動(dòng)態(tài)類型與靜態(tài)類型在一種語言中房轿,這樣可以在必要的時(shí)候取長(zhǎng)補(bǔ)短,Boo就是一個(gè)很好的試驗(yàn)性例子所森。
③ Objective-C的動(dòng)態(tài)運(yùn)行性
Objective-C語言是C語言的一個(gè)子類囱持,所以objective-c是一個(gè)靜態(tài)語言,但是Objective-C的三大特性之一的多態(tài)性讓其擁有了動(dòng)態(tài)性焕济。
oc的動(dòng)態(tài)性讓程序可以在運(yùn)行時(shí)判斷其該有的行為纷妆,而不是像c等靜態(tài)語言一樣在編譯構(gòu)建時(shí)就確定下來。它的動(dòng)態(tài)性主要體現(xiàn)在一下三個(gè)方面:
如id類型晴弃。實(shí)際上靜態(tài)類型因?yàn)槠涔潭ㄐ院涂深A(yù)知性而使用得更加廣泛掩幢。靜態(tài)類型是強(qiáng)類型,而動(dòng)態(tài)類型屬于弱類型上鞠。運(yùn)行時(shí)決定接收者际邻。
這里補(bǔ)充講一下強(qiáng)、弱類型:語言有無類型旗国、強(qiáng)類型和弱類型三種枯怖。無類型的不做任何檢查,甚至不區(qū)分指令和數(shù)據(jù)能曾;弱類型的檢查很弱度硝,僅能區(qū)分指令和數(shù)據(jù);強(qiáng)類型的嚴(yán)格在編譯期進(jìn)行檢查寿冕。強(qiáng)類型語言在沒有強(qiáng)制類型轉(zhuǎn)化前蕊程,不允許兩種不同類型的變量相互操作
讓代碼在運(yùn)行時(shí)判斷需要調(diào)用什么方法,而不是在編譯時(shí)驼唱。與其他面向?qū)ο笳Z言一樣藻茂,方法調(diào)用和代碼并沒有在編譯時(shí)連接在一起,而是在消息發(fā)送時(shí)才進(jìn)行連接玫恳。運(yùn)行時(shí)決定調(diào)用哪個(gè)方法辨赐。
讓程序在運(yùn)行時(shí)添加代碼模塊以及其他資源。用戶可以根據(jù)需要加載一些可執(zhí)行代碼和資源京办,而不是在啟動(dòng)時(shí)就加載所有組件掀序。可執(zhí)行代碼中可以含有和程序運(yùn)行時(shí)整合的新類惭婿。
對(duì)象是運(yùn)行時(shí)類的一個(gè)實(shí)例不恭。在類里聲明了的實(shí)例變量和方法叶雹,它的每個(gè)實(shí)例都在內(nèi)存中擁有同樣的實(shí)例變量,以及指向那些方法的指針换吧。在oc中對(duì)象永遠(yuǎn)是通過指針來引用的折晦。
MVC满着,MVP 和 MVVM 的圖示
3.為什么代理要用weak?代理的delegate和dataSource有什么區(qū)別暴拄?block和代理的區(qū)別?
代理屬性都用weak或是assign修飾, 現(xiàn)整理下weak(assign)與strong(retain)修飾區(qū)別:
@property (nonatomic, weak) iddelegate;
weak:指明該對(duì)象并不負(fù)責(zé)保持delegate這個(gè)對(duì)象漓滔,delegate這個(gè)對(duì)象的銷毀由外部控制
@property (nonatomic, strong) iddelegate;
strong:該對(duì)象強(qiáng)引用delegate,外界不能銷毀delegate對(duì)象乖篷,會(huì)導(dǎo)致循環(huán)引用(Retain MainVC)
Datasource 是在告訴使用者之前的view中都有什么東西响驴,有什么屬性啊,屬性的值都是多少撕蔼,是只關(guān)于數(shù)據(jù)的東西豁鲤。
Delegate 是在告訴使用者之前的view有什么方法可以供我調(diào)用。
一個(gè)是數(shù)據(jù)鲸沮,一個(gè)是操作.
首先兩者作用是一樣的琳骡,都是進(jìn)行單一回調(diào)。不同的是讼溺,delegate是個(gè)對(duì)象楣号,然后用過一個(gè)對(duì)象自己調(diào)用代理協(xié)議函數(shù)來完成整個(gè)流程。block是傳遞一個(gè)函數(shù)指針怒坯,利用函數(shù)指針執(zhí)行來進(jìn)行回調(diào)炫狱。還有在內(nèi)存管理上需要注意,delegate不需要保存引用剔猿。block對(duì)引用數(shù)據(jù)有copy的處理视译。
屬性的組成: @property = ivar + getter + setter;
實(shí)例變量+get方法+set方法,也就是說使用@property 系統(tǒng)會(huì)自動(dòng)生成setter和getter方法;
我們經(jīng)常使用assign,weak,strong,copy,nonatomic,atomic,readonly等關(guān)鍵字汪茧,下面我們列個(gè)表格去歸納一下屬性關(guān)鍵字具體作用:
@synthesize和@dynamic區(qū)別, 在聲明property屬性后椅亚,有2種實(shí)現(xiàn)選擇:@synthesize編譯器期間,讓編譯器自動(dòng)生成getter/setter方法舱污。當(dāng)有自定義的存或取方法時(shí)什往,自定義會(huì)屏蔽自動(dòng)生成該方法@dynamic告訴編譯器,不自動(dòng)生成getter/setter方法慌闭,避免編譯期間產(chǎn)生警告别威,然后由自己實(shí)現(xiàn)存取方法÷刻蓿或存取方法在運(yùn)行時(shí)動(dòng)態(tài)創(chuàng)建綁定:主要使用在CoreData的實(shí)現(xiàn)NSManagedObject子類時(shí)使用省古,由CoreData框架在程序運(yùn)行的時(shí)動(dòng)態(tài)生成子類屬性
iOS_研究(3)_@property 屬性的本質(zhì)是什么?
對(duì)于基本數(shù)據(jù)類型默認(rèn)關(guān)鍵字是atomic,readwrite,assign
對(duì)于普通的OC對(duì)象atomic,readwrite,strong
6.NSString為什么要用copy關(guān)鍵字丧失,如果用strong會(huì)有什么問題豺妓?(注意:這里沒有說用strong就一定不行。使用copy和strong是看情況而定的)
怎么用 copy 關(guān)鍵字布讹?
如何讓自己的類用 copy 修飾符琳拭?如何重寫帶 copy 關(guān)鍵字的 setter?
8.可變集合類 和 不可變集合類的 copy 和 mutablecopy有什么區(qū)別?如果是集合是內(nèi)容復(fù)制的話描验,集合里面的元素也是內(nèi)容復(fù)制么白嘁?
首先我們要先明白一個(gè)概念,什么是淺復(fù)制膘流,單層深復(fù)制絮缅,完全復(fù)制(每一層都深復(fù)制)
淺復(fù)制也就是所說的指針復(fù)制,并沒有進(jìn)行對(duì)象復(fù)制;
單層深復(fù)制呼股,也就是我們經(jīng)常說的深復(fù)制耕魄,我這里說的單層深復(fù)制是對(duì)于集合類所說的(即NSArray,NSDictionary,NSSet),單層深復(fù)制指的是只復(fù)制了該集合類的最外層彭谁,里邊的元素沒有復(fù)制吸奴,(即這兩個(gè)集合類的地址不一樣,但是兩個(gè)集合里所存儲(chǔ)的元素的地址是一樣的);
完全復(fù)制缠局,指的是完全復(fù)制整個(gè)集合類则奥,也就是說兩個(gè)集合地址不一樣,里邊所存儲(chǔ)的元素地址也不一樣;
明白了這三個(gè)概念之后甩鳄,我們就來說一下他們的區(qū)別所在:
[immutableObject copy]//淺復(fù)制[immutableObject mutableCopy]//深復(fù)制[mutableObject copy]//深復(fù)制[mutableObject mutableCopy]//深復(fù)制
結(jié)論:不可變進(jìn)行copy是淺復(fù)制,mutableCopy是深復(fù)制妙啃,可變的copy档泽,mutableCopy都是深復(fù)制
集合類(NSArray,NSDictionary, NSSet):
[immutableObject copy]//淺復(fù)制[immutableObject mutableCopy]//單層深復(fù)制[mutableObject copy]//單層深復(fù)制[mutableObject mutableCopy]//單層深復(fù)制
結(jié)論:不可變進(jìn)行copy是淺復(fù)制揖赴,mutableCopy是單層深復(fù)制馆匿,可變的copy,mutableCopy都是單層深復(fù)制
那么如何實(shí)現(xiàn)多層復(fù)制呢燥滑?
以NSArray舉例說明
NSArray*copyArray = [[NSArrayalloc] initWithArray:array copyItems:YES];// 完全復(fù)制
以上我們所說的兩種情況默認(rèn)都實(shí)現(xiàn)了NSCopying和NSMutableCopying協(xié)議
對(duì)于自定義繼承自NSObject的類
copy需要實(shí)現(xiàn)NSCopying協(xié)議渐北,然后實(shí)現(xiàn)以下方法,否則copy會(huì)crash
-(id)copyWithZone:(NSZone *)zone {? CopyObject? *copy= [[[selfclass] alloc] init];copy.name =self.name;copy.mobile =self.mobile;copy.company =self.company;copy.descInfo =self.descInfo;returncopy;}mutableCopy時(shí)铭拧,需要實(shí)現(xiàn)NSMutableCopying協(xié)議赃蛛,否則mutableCopy會(huì)crash-(id)mutableCopyWithZone:(NSZone *)zone {? ? ? MutableCopyObject? *mutableCopy = [[[selfclass] alloc] init];? ? ? mutableCopy.name =self.name;? ? ? mutableCopy.mobile =self.mobile;? ? ? mutableCopy.company =self.company;? ? ? mutableCopy.descInfo =self.descInfo;returnmutableCopy;}
9.為什么IBOutlet修飾的UIView也適用weak關(guān)鍵字恃锉?
因?yàn)楫?dāng)我們將控件拖到Storyboard上,相當(dāng)于新創(chuàng)建了一個(gè)對(duì)象呕臂,而這個(gè)對(duì)象是加到視圖控制器的view上破托,view有一個(gè)subViews屬性,這個(gè)屬性是一個(gè)數(shù)組歧蒋,里面是這個(gè)view的所有子view土砂,而我們加的控件就位于這個(gè)數(shù)組中,那么說明谜洽,實(shí)際上我們的控件對(duì)象是屬于view的萝映,也就是說view對(duì)加到它上面的控件是強(qiáng)引用。當(dāng)我們使用Outlet屬性的時(shí)候阐虚,我們是在viewController里面使用序臂,而這個(gè)Outlet屬性是有view來進(jìn)行強(qiáng)引用的,我們?cè)趘iewController里面僅僅是對(duì)其使用敌呈,并沒有必要擁有它贸宏,所以是weak的。
如果將weak改為strong磕洪,也是沒有問題的吭练,并不會(huì)造成強(qiáng)引用循環(huán)。當(dāng)viewController的指針指向其他對(duì)象或者為nil析显,這個(gè)viewController銷毀鲫咽,那么對(duì)控件就少了一個(gè)強(qiáng)引用指針。然后它的view也隨之銷毀谷异,那么subViews也不存在了分尸,那么控件就又少了一個(gè)強(qiáng)引用指針,如果沒有其他強(qiáng)引用歹嘹,那么這個(gè)控件也會(huì)隨之銷毀箩绍。
不過,既然沒有必將Outlet屬性設(shè)置為strong尺上,那么用weak就好了;一個(gè)控件可以在viewController里面有多個(gè)Outlet屬性材蛛,就相當(dāng)于一個(gè)對(duì)象,可以有多個(gè)指針指向它(多個(gè)引用)怎抛。但是一個(gè)Outlet屬性只能對(duì)應(yīng)一個(gè)控件卑吭,也就是說,如果有button1和button2马绝,button1在viewController里面有一個(gè)名為button的Outlet屬性豆赏,此時(shí)button指向button1,但是如果用button2給button重新賦值,那么此時(shí)button指向button2掷邦。也就是說白胀,后來的覆蓋原來的。
一個(gè)控件可以在viewController里面觸發(fā)多個(gè)IBAction耙饰。比如有一個(gè)button控件纹笼,在viewController里面有幾個(gè)方法,那么點(diǎn)擊button苟跪,會(huì)觸發(fā)所有的這些方法。如果我有多個(gè)控件蔓涧,比如button1,button2,button3件已,它們也可以同時(shí)綁定一個(gè)buttonClick方法,無論點(diǎn)擊button1,button2還是button3元暴,都會(huì)觸發(fā)這個(gè)buttonClick方法篷扩。
上面說了,button1,button2,button3有可能都觸發(fā)buttonClick方法茉盏,如果想在buttonClick方法里面區(qū)分到底是哪個(gè)button觸發(fā)的可能有好幾種做法鉴未。
可以給這三個(gè)button各設(shè)置一個(gè)Outlet屬性,然后在buttonClick里面判斷sender和哪個(gè)Outlet屬性是同一對(duì)象鸠姨,這樣就可以區(qū)分了铜秆。但是很明顯,這樣并不合理讶迁,因?yàn)閯?chuàng)建的三個(gè)屬性有些浪費(fèi)连茧。
我們可以給三個(gè)button各加一個(gè)tag,在buttonClick里面通過switch(或者if…)判斷巍糯,sender的tag和給各個(gè)button加上的tag是否一致啸驯,如果一致則為同一對(duì)象。要慎用tag祟峦。因?yàn)関iew有一個(gè)viewWithTag:方法罚斗,可以在view的子view里面找到和我們傳入的tag相同的view,這樣哪怕不給這個(gè)控件創(chuàng)建Outlet屬性宅楞,也可以通過tag找到這個(gè)對(duì)象针姿。但是很明顯,這個(gè)方法要遍歷子view咱筛,比較每個(gè)子view的tag搓幌,這樣效率并不高,所以盡量要避免這種情況迅箩。
10.nonatomic和atomic的區(qū)別溉愁?atomic是絕對(duì)的線程安全么?為什么?如果不是拐揭,那應(yīng)該如何實(shí)現(xiàn)撤蟆?
在默認(rèn)情況下,由編譯器所合成的方法會(huì)通過鎖定機(jī)制確保其原子性(atomicity)堂污。如果屬性具備nonatomic特質(zhì)家肯,則不需要同步鎖。
具備atomic特質(zhì)的獲取方法會(huì)通過鎖定機(jī)制來確保其操作的原子性盟猖。也就是說讨衣,如果兩個(gè)線程同時(shí)讀取一個(gè)屬性,那么不論何時(shí)式镐,總能看到有效的屬性值反镇。
如果不加鎖的話(或者說使用nonatomic語義),那么當(dāng)其中一個(gè)線程正在改寫某屬性值的時(shí)候娘汞,另外一個(gè)線程也許會(huì)突然闖入歹茶,把尚未修改好的屬性值讀取出來。發(fā)證這種情況時(shí)你弦,線程讀取道德屬性值肯能不對(duì)惊豺。
一般iOS程序中,所有屬性都聲明為nonatomic禽作。這樣做的原因是:
在iOS中使用同步鎖的開銷比較大尸昧, 這會(huì)帶來性能問題。一般情況下并不要求屬性必須是“原子的”领迈,因?yàn)檫@并不能保證“線程安全”(thread safety)彻磁,若要實(shí)現(xiàn)“線程安全”的操作,還需采用更為深層的鎖定機(jī)制才行狸捅。
例如:一個(gè)線程在連續(xù)多次讀取某個(gè)屬性值的過程中有別的線程在同時(shí)改寫該值衷蜓,那么即便將屬性聲明為atomic,也還是會(huì)讀取到不同的屬性值尘喝。因此磁浇,ios程序一般都會(huì)使用nonatomic屬性。但是在Mac OS X程序時(shí)朽褪, 使用atomic屬性通常都不會(huì)有性能瓶頸;
nonatomic的內(nèi)存管理語義是非原子性的,非原子性的操作本來就是線程不安全缔赠,而atomic的操作是原子性的衍锚,但并不意味著他就是線程安全的,它會(huì)增加正確的幾率嗤堰,能夠更好的避免線程錯(cuò)誤戴质,但仍舊是不安全的。
為了說atomic與nonatomic的本質(zhì)區(qū)別其實(shí)也就是在setter方法上的操作不。nonatomic的實(shí)現(xiàn):
- (void)setCurrentImage:(UIImage *)currentImage{? ? if (_currentImage != currentImage) {? ? ? ? [_currentImage release];? ? ? ? _currentImage = [currentImage retain];? ? ? ? //dosomething? ? }}- (UIImage *)currentImage{? ? return _currentImage;}? ? ? ? atomic的實(shí)現(xiàn):- (void)setCurrentImage:(UIImage *)currentImage{? ? @synchronized(self) {? ? ? ? if (_currentImage != currentImage) {? ? ? ? ? ? [_currentImage release];? ? ? ? ? ? _currentImage = [currentImage retain];? ? ? ? ? ? //dosomething? ? ? ? }? ? }}- (UIImage *)currentImage{? ? @synchronized(self) {? ? ? ? return _currentImage;}}Using the @synchronized DirectiveThe @synchronized directive is a convenient way tocreatemutex locksonthe flyinObjective-C code. The @synchronized directive does whatanyother mutexlockwoulddo—it prevents different threadsfromacquiring the samelockatthe sametime.Inthiscase, however, youdonothavetocreatethe mutexorlockobject directly. Instead, you simply useanyObjective-C objectasalocktoken,asshowninthe following example:
- (void)myMethod:(id)anObj{@synchronized(anObj)? ? {//Everything between the bracesisprotectedbythe@synchronizeddirective.? ? }}
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時(shí)告匠,雖然對(duì)屬性的讀和寫是原子性的戈抄,但是仍然可能出現(xiàn)線程錯(cuò)誤:當(dāng)線程A進(jìn)行寫操作,這時(shí)其他線程的讀或者寫操作會(huì)因?yàn)榈仍摬僮鞫却笞ā.?dāng)A線程的寫操作結(jié)束后划鸽,B線程進(jìn)行寫操作,所有這些不同線程上的操作都將依次順序執(zhí)行——也就是說戚哎,如果一個(gè)線程正在執(zhí)行 getter/setter裸诽,其他線程就得等待。如果有線程C在A線程讀操作之前release了該屬性建瘫,那么還會(huì)導(dǎo)致程序崩潰崭捍。所以僅僅使用atomic并不會(huì)使得線程安全,我們還要為線程添加lock來確保線程的安全啰脚。
更準(zhǔn)確的說應(yīng)該是讀寫安全,但并不是線程安全的实夹,因?yàn)閯e的線程還能進(jìn)行讀寫之外的其他操作橄浓。線程安全需要開發(fā)者自己來保證。
其實(shí)無論是否是原子性的只是針對(duì)于getter和setter而言亮航,比如用atomic去操作一個(gè)NSMutableArray 荸实,如果一個(gè)線程循環(huán)讀數(shù)據(jù),一個(gè)線程循環(huán)寫數(shù)據(jù)缴淋,肯定會(huì)產(chǎn)生內(nèi)存問題准给,這個(gè)就跟getter和setter就木有關(guān)系了。
11.UICollectionView自定義layout如何實(shí)現(xiàn)重抖?
關(guān)于自定義UICollectionViewLayout的一點(diǎn)個(gè)人理解
12.用StoryBoard開發(fā)界面有什么弊端露氮?如何避免?
Storyboard在某些角度上钟沛,是難以維護(hù)的畔规。我所遇到過的實(shí)際情況是,公司一個(gè)項(xiàng)目的2.0版本恨统,設(shè)計(jì)師希望替換原有字體叁扫。然而原來項(xiàng)目的每一個(gè)Label都是采用Storyboard來定義字體的,因此替換新字體需要在Storyboard中更改每一個(gè)Label畜埋。
幸虧我們知道Storyboard的源文件是XML莫绣,最終寫了一個(gè)讀取-解析-替換腳本來搞定這件事。
當(dāng)項(xiàng)目達(dá)到一定的規(guī)模悠鞍,即使是高性能的MacBook Pro,在打開Storyboard是也會(huì)有3-5秒的讀取時(shí)間对室。無論是只有幾個(gè)Scene的小東西,還是幾十個(gè)Scene的龐然大物,都無法避免软驰。Scene越多的文件涧窒,打開速度越慢(從另一個(gè)方面說明了分割大故事板的重要性)。
讓人沮喪的是锭亏,這個(gè)造成卡頓的項(xiàng)目規(guī)模并不是太難達(dá)到纠吴。
我猜想是由于每一次打開都需要進(jìn)行I/O操作造成的,Apple對(duì)這一塊的緩存優(yōu)化沒有做到位慧瘤〈饕眩可能是由于Storyboard占用了太多內(nèi)存,難以在內(nèi)存中進(jìn)行緩存锅减。Whatever,這個(gè)問題總是讓人困擾的糖儡。
然而需要指出的是,采用Storyboard開發(fā)或采用純代碼開發(fā)的App怔匣,在真機(jī)的運(yùn)行效率上握联,并沒有太大的區(qū)別。
Storyboard的初學(xué)者應(yīng)該對(duì)此深有體會(huì)每瞒。排除BAD_EXCUSE錯(cuò)誤不說金闽,單單是有提示的錯(cuò)誤,就足以讓人在代碼和Storyboard之間來回摸索剿骨,卻無法找到解決方案代芜。
一個(gè)典型的例子是,在代碼中刪除了IBOUTLET屬性或者IBAction方法浓利,但是卻忘了在Storyboard中刪除對(duì)應(yīng)的連接挤庇,運(yùn)行后crash。然而控制臺(tái)只會(huì)輸出一些模糊其詞的錯(cuò)誤描述贷掖。
*** Terminating app duetouncaught exception'NSUnknownKeyException',reason:'[ setValue:forUndefinedKey:]:thisclassisnotkeyvalue coding-compliantforthekeydrawButton.'
最后一方面是其提供的便利嫡秕,另一方面是Apple對(duì)Storyboard的大力支持。這一點(diǎn)宏觀上看羽资,可以在以往對(duì)Storyboard的改進(jìn)和增強(qiáng)上看出淘菩,微觀上看,幾乎所有iOS 8之后的simple code都或多或少采用了Storyboard作為界面開發(fā)工具;
那改如何避免這些弊端呢, 參考以下文章:
iOS項(xiàng)目開發(fā)實(shí)戰(zhàn)——storyboard設(shè)置界面技巧與注意事項(xiàng)
13.進(jìn)程和線程的區(qū)別屠升?同步異步的區(qū)別潮改?并行和并發(fā)的區(qū)別?
進(jìn)程和線程:
進(jìn)程中所包含的一個(gè)或多個(gè)執(zhí)行單元稱為線程(thread)腹暖。比如一個(gè)應(yīng)用程序就是一個(gè)進(jìn)程, 而它又包含了多個(gè)線程;主要差別在于它們是不同的操作系統(tǒng)資源管理方式汇在。進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后脏答,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響糕殉,而線程只是一個(gè)進(jìn)程中的不同執(zhí)行路徑亩鬼。線程有自己的堆棧和局部變量,但線程之間沒有單獨(dú)的地址空間阿蝶,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉雳锋,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時(shí)羡洁,耗費(fèi)資源較大玷过,效率要差一些。但對(duì)于一些要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作筑煮,只能用線程辛蚊,不能用進(jìn)程;
在進(jìn)行網(wǎng)絡(luò)編程時(shí),我們通常會(huì)看到同步真仲、異步袋马、阻塞、非阻塞四種調(diào)用方式以及他們的組合秸应。
其中同步方式虑凛、異步方式主要是由客戶端(client)控制的,具體如下:
所謂同步软啼,就是發(fā)出一個(gè)功能調(diào)用時(shí)卧檐,在沒有得到結(jié)果之前,該調(diào)用就不返回或繼續(xù)執(zhí)行后續(xù)操作焰宣。
根據(jù)這個(gè)定義,Java中所有方法都是同步調(diào)用捕仔,應(yīng)為必須要等到結(jié)果后才會(huì)繼續(xù)執(zhí)行匕积。我們?cè)谡f同步、異步的時(shí)候榜跌,一般而言是特指那些需要其他端協(xié)作或者需要一定時(shí)間完成的任務(wù)闪唆。
簡(jiǎn)單來說,同步就是必須一件一件事做钓葫,等前一件做完了才能做下一件事悄蕾。
例如:B/S模式中的表單提交,具體過程是:客戶端提交請(qǐng)求->等待服務(wù)器處理->處理完畢返回础浮,在這個(gè)過程中客戶端瀏覽器不能做其他事帆调。
異步與同步相對(duì),當(dāng)一個(gè)異步過程調(diào)用發(fā)出后豆同,調(diào)用者在沒有得到結(jié)果之前番刊,就可以繼續(xù)執(zhí)行后續(xù)操作。當(dāng)這個(gè)調(diào)用完成后影锈,一般通過狀態(tài)芹务、通知和回調(diào)來通知調(diào)用者蝉绷。對(duì)于異步調(diào)用,調(diào)用的返回并不受調(diào)用者控制枣抱。
總結(jié)來說熔吗,同步和異步的區(qū)別:請(qǐng)求發(fā)出后,是否需要等待結(jié)果佳晶,才能繼續(xù)執(zhí)行其他操作桅狠。
并行(parallellism)和并發(fā)(concurrency)的區(qū)別:
并行是指兩個(gè)或者多個(gè)事件在同一時(shí)刻發(fā)生;而并發(fā)是指兩個(gè)或多個(gè)事件在同一時(shí)間間隔發(fā)生宵晚。
并發(fā),是在同一個(gè)cpu上同時(shí)(不是真正的同時(shí)淤刃,而是看來是同時(shí)晒他,因?yàn)閏pu要在多個(gè)程序間切換)運(yùn)行多個(gè)程序;
并發(fā)和并行的區(qū)別
使用全局變量主要由于多個(gè)線程可能更改全局變量逸贾,因此全局變量最好聲明為violate
使用消息實(shí)現(xiàn)通信在Windows程序設(shè)計(jì)中陨仅,每一個(gè)線程都可以擁有自己的消息隊(duì)列(UI線程默認(rèn)自帶消息隊(duì)列和消息循環(huán),工作線程需要手動(dòng)實(shí)現(xiàn)消息循環(huán))铝侵,因此可以采用消息進(jìn)行線程間通信sendMessage,postMessage灼伤。
1)定義消息#defineWM_THREAD_SENDMSG=WM_USER+20;2)添加消息函數(shù)聲明afx_msgintOnTSendmsg();3)添加消息映射ON_MESSAGE(WM_THREAD_SENDMSG,OnTSM)4)添加OnTSM()的實(shí)現(xiàn)函數(shù);5)在線程函數(shù)中添加PostMessage消息Post函數(shù)
Event對(duì)象有兩種狀態(tài):有信號(hào)和無信號(hào)咪鲜,線程可以監(jiān)視處于有信號(hào)狀態(tài)的事件狐赡,以便在適當(dāng)?shù)臅r(shí)候執(zhí)行對(duì)事件的操作。
1)創(chuàng)建一個(gè)CEvent類的對(duì)象:CEvent threadStart;它默認(rèn)處在未通信狀態(tài)疟丙;2)threadStart.SetEvent();使其處于通信狀態(tài)颖侄;3)調(diào)用WaitForSingleObject()來監(jiān)視CEvent對(duì)象
線程間的通信、同步方式與進(jìn)程間通信方式
15.GCD的一些常用的函數(shù)享郊?(group览祖,barrier,信號(hào)量炊琉,線程同步)
dispatch_groupdispatch_barrierdispatch_semaphore(信號(hào)量)附:iOSGCD線程同步方法
ios多線程——鎖(解決多線程搶奪同一塊資源的問題)
17.數(shù)據(jù)持久化的幾個(gè)方案(fmdb用沒用過)
plist文件(屬性列表)
preference(偏好設(shè)置)
NSKeyedArchiver(歸檔)
SQLite 3
CoreData
iOS中幾種數(shù)據(jù)持久化方案
1. – (BOOL)application:(UIApplication)application didFinishLaunchingWithOptions:(NSDictionary)launchOptions NS_AVAILABLE_IOS(3_0);
當(dāng)應(yīng)用程序啟動(dòng)時(shí)(不包括已在后臺(tái)的情況下轉(zhuǎn)到前臺(tái))悼泌,調(diào)用此回調(diào)松捉。launchOptions是啟動(dòng)參數(shù),假如用戶通過點(diǎn)擊push通知啟動(dòng)的應(yīng)用馆里,這個(gè)參數(shù)里會(huì)存儲(chǔ)一些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)用程序全新啟動(dòng)可柿,或者在后臺(tái)轉(zhuǎn)到前臺(tái),完全激活時(shí)丙者,都會(huì)調(diào)用這個(gè)方法复斥。如果應(yīng)用程序是以前運(yùn)行在后臺(tái),這時(shí)可以選擇刷新用戶界面械媒。
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)狀態(tài)轉(zhuǎn)入后臺(tái)時(shí)目锭,調(diào)用此方法。使用此方法來釋放資源共享纷捞,保存用戶數(shù)據(jù)痢虹,無效計(jì)時(shí)器,并儲(chǔ)存足夠的應(yīng)用程序狀態(tài)信息的情況下被終止后主儡,將應(yīng)用 程序恢復(fù)到目前的狀態(tài)奖唯。如果您的應(yīng)用程序支持后臺(tái)運(yùn)行,這種方法被調(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),將要進(jìn)行動(dòng)前臺(tái)運(yùn)行狀態(tài)時(shí)寂汇,會(huì)調(diào)用此方法病往。
如果應(yīng)用不在后臺(tái)狀態(tài),而是直接啟動(dòng)骄瓣,則不會(huì)回調(diào)此方法停巷。
從后臺(tái)到前臺(tái)2, 4; 第一次啟動(dòng)1, 2; 從前臺(tái)到后臺(tái)3;
iOS APP啟動(dòng)時(shí)所有方法的調(diào)用順序分析
19.NSCache優(yōu)于NSDictionary的幾點(diǎn)?
NSCache勝過NSDictionary之處在于榕栏,當(dāng)系統(tǒng)資源將要耗盡時(shí)叠穆,它可以自動(dòng)刪減緩存。如果采用普通的字典臼膏,那么就要自己編寫掛鉤,在系統(tǒng)發(fā)出“低內(nèi)存”通知時(shí)手工刪減緩存示损。
NSCache并不會(huì)“拷貝”鍵渗磅,而是會(huì)“保留”它。此行為用NSDictionary也可以實(shí)現(xiàn)检访,然而需要編寫相當(dāng)復(fù)雜的代碼始鱼。NSCache對(duì)象不拷貝鍵的原因在于:很多時(shí)候,鍵都是不支持拷貝操作的對(duì)象來充當(dāng)?shù)拇喙蟆R虼艘角澹琋SCache不會(huì)自動(dòng)拷貝鍵,所以說卖氨,在鍵不支持拷貝操作的情況下会烙,該類用起來比字典更方便负懦。另外,NSCache是線程安全的柏腻,而NSDictionary則絕對(duì)不具備此優(yōu)勢(shì)纸厉。
20.知不知道Designated Initializer?使用它的時(shí)候有什么需要注意的問題五嫂?
iOS: 聊聊 Designated Initializer(指定初始化函數(shù))
正確編寫Designated Initializer的幾個(gè)原則
21.實(shí)現(xiàn)description方法能取到什么效果颗品?
一般情況下,我們?cè)谑褂肗SLog 和 %@ 輸出某個(gè)對(duì)象時(shí)沃缘,就會(huì)調(diào)用這個(gè)對(duì)象的 description 方法躯枢,它的返回值就是 NSString 字符串類型,所以 description 默認(rèn)實(shí)現(xiàn)返回的格式是 <類名: 對(duì)象的內(nèi)存地址>
如圖:
以上輸出實(shí)現(xiàn)的具體步驟為:
①調(diào)用對(duì)象p的-description方法②拿到-description方法的返回值(NSString*)顯示到屏幕上③-description方法默認(rèn)返回的是“類名+內(nèi)存地址”
那么槐臀,既然description方法的默認(rèn)實(shí)現(xiàn)是返回類名和對(duì)象的內(nèi)存地址锄蹂,所以在必要情況下,我們需要重寫description方法以達(dá)到改變輸出結(jié)果目的峰档,覆蓋description方法的默認(rèn)實(shí)現(xiàn)败匹,比如重寫上述代碼 Person 類的 description方法,返回_age和_name成員變量的值:
重寫完description方法后讥巡,再調(diào)用NSLog(@”%@”,p)時(shí)輸出結(jié)果不再是<類名: 內(nèi)存地址>掀亩,而是返回的字符串:
22.objc使用什么機(jī)制管理對(duì)象內(nèi)存?
MRC(manual retain-release)手動(dòng)內(nèi)存管理
ARC(automatic reference counting)自動(dòng)引用計(jì)數(shù)
Garbage collection (垃圾回收)欢顷。但是iOS不支持垃圾回收, ARC作為L(zhǎng)LVM3.0編譯器的一項(xiàng)特性, 在iOS5.0 (Xcode4) 版本后推出的槽棍。
ARC的判斷準(zhǔn)則, 只要沒有強(qiáng)指針指向?qū)ο? 對(duì)象就會(huì)被釋放.
iOS開發(fā)系列—Objective-C之內(nèi)存管理