1. Object-c的類可以多重繼承么?可以實(shí)現(xiàn)多個接口么?Category是什么?重寫一個類的方式用繼承好還是分類好?為什么?
答: Object-c的類不可以多重繼承;可以實(shí)現(xiàn)多個接口修肠,通過實(shí)現(xiàn)多個接口可以完成C++的多重繼承;Category是類別,一般情況用分類好,用Category去重寫類的方法赊琳,僅對本Category有效,不會影響到其他類與原有類的關(guān)系。
2. #import 跟#include 又什么區(qū)別,@class呢, #import<> 跟 #import””又什么區(qū)別?
答:#import是Objective-C導(dǎo)入頭文件的關(guān)鍵字外盯,#include是C/C++導(dǎo)入頭文件的關(guān)鍵字,使用#import頭文件會自動只導(dǎo)入一次,不會重復(fù)導(dǎo)入翼雀,相當(dāng)于#include和#pragma once;@class告訴編譯器某個類的聲明饱苟,當(dāng)執(zhí)行時,才去查看類的實(shí)現(xiàn)文件锅纺,可以解決頭文件的相互包含;#import<>用來包含系統(tǒng)的頭文件掷空,#import””用來包含用戶頭文件。
3. 屬性readwrite囤锉,readonly坦弟,assign,retain官地,copy酿傍,nonatomic 各是什么作用,在那種情況下用?
答:
1). readwrite 是可讀可寫特性;需要生成getter方法和setter方法時
2). readonly 是只讀特性 只會生成getter方法 不會生成setter方法 ;不希望屬性在類外改變
3). assign 是賦值特性驱入,setter方法將傳入?yún)?shù)賦值給實(shí)例變量;僅設(shè)置變量時;
4). retain 表示持有特性赤炒,setter方法將傳入?yún)?shù)先保留,再賦值亏较,傳入?yún)?shù)的retaincount會+1;
5). copy 表示賦值特性莺褒,setter方法將傳入對象復(fù)制一份;需要完全一份新的變量時。
6).nonatomic 非原子操作雪情,決定編譯器生成的setter getter是否是原子操作遵岩,atomic表示多線程安全,一般使用nonatomic
4.寫一個setter方法用于完成@property (nonatomic,retain)NSString *name,寫一個setter方法用于完成@property(nonatomic巡通,copy)NSString *name
答:
- (void) setName:(NSString*) str
{
[str retain];
[name release];
name = str;
}
- (void)setName:(NSString *)str
{
id t = [str copy];
[name release];
name = t;
}
5.對于語句NSString*obj = [[NSData alloc] init]; obj在編譯時和運(yùn)行時分別時什么類型的對象?
答: 編譯時是NSString的類型;運(yùn)行時是NSData類型的對象
6.常見的object-c的數(shù)據(jù)類型有那些尘执, 和C的基本數(shù)據(jù)類型有什么區(qū)別?如:NSInteger和int
答:object-c的數(shù)據(jù)類型有NSString,NSNumber宴凉,NSArray誊锭,NSMutableArray,NSData等等弥锄,這些都是class丧靡,創(chuàng)建后便是對象,而C語言的基本數(shù)據(jù)類型int籽暇,只是一定字節(jié)的內(nèi)存空間窘行,用于存放數(shù)值;NSInteger是基本數(shù)據(jù)類型,并不是NSNumber的子類图仓,當(dāng)然也不是NSObject的子類罐盔。NSInteger是基本數(shù)據(jù)類型Int或者Long的別名(NSInteger的定義typedef long NSInteger),它的區(qū)別在于救崔,NSInteger會根據(jù)系統(tǒng)是32位還是64位來決定是本身是int還是Long惶看。
7.id 聲明的對象有什么特性?
答:Id 聲明的對象具有運(yùn)行時的特性,即可以指向任意類型的objcetive-c的對象;
8.Objective-C如何對內(nèi)存管理的,說說你的看法和解決方法?
答:Objective-C的內(nèi)存管理主要有三種方式ARC(自動內(nèi)存計數(shù))六孵、手動內(nèi)存計數(shù)纬黎、內(nèi)存池。
1). (Garbage Collection)自動內(nèi)存計數(shù):這種方式和java類似劫窒,在你的程序的執(zhí)行過程中本今。始終有一個高人在背后準(zhǔn)確地幫你收拾垃圾,你不用考慮它什么時候開始工作,怎樣工作冠息。你只需要明白挪凑,我申請了一段內(nèi)存空間,當(dāng)我不再使用從而這段內(nèi)存成為垃圾的時候逛艰,我就徹底的把它忘記掉躏碳,反正那個高人會幫我收拾垃圾。遺憾的是散怖,那個高人需要消耗一定的資源菇绵,在攜帶設(shè)備里面,資源是緊俏商品所以iPhone不支持這個功能镇眷。所以“Garbage Collection”不是本入門指南的范圍咬最,對“Garbage Collection”內(nèi)部機(jī)制感興趣的同學(xué)可以參考一些其他的資料,不過說老實(shí)話“Garbage Collection”不大適合適初學(xué)者研究欠动。
解決: 通過alloc – initial方式創(chuàng)建的, 創(chuàng)建后引用計數(shù)+1, 此后每retain一次引用計數(shù)+1, 那么在程序中做相應(yīng)次數(shù)的release就好了.
2). (Reference Counted)手動內(nèi)存計數(shù):就是說永乌,從一段內(nèi)存被申請之后,就存在一個變量用于保存這段內(nèi)存被使用的次數(shù)翁垂,我們暫時把它稱為計數(shù)器铆遭,當(dāng)計數(shù)器變?yōu)?的時候,那么就是釋放這段內(nèi)存的時候沿猜。比如說枚荣,當(dāng)在程序A里面一段內(nèi)存被成功申請完成之后,那么這個計數(shù)器就從0變成1(我們把這個過程叫做alloc)啼肩,然后程序B也需要使用這個內(nèi)存橄妆,那么計數(shù)器就從1變成了2(我們把這個過程叫做retain)。緊接著程序A不再需要這段內(nèi)存了祈坠,那么程序A就把這個計數(shù)器減1(我們把這個過程叫做release);程序B也不再需要這段內(nèi)存的時候害碾,那么也把計數(shù)器減1(這個過程還是release)。當(dāng)系統(tǒng)(也就是Foundation)發(fā)現(xiàn)這個計數(shù)器變 成員了0赦拘,那么就會調(diào)用內(nèi)存回收程序把這段內(nèi)存回收(我們把這個過程叫做dealloc)慌随。順便提一句,如果沒有Foundation躺同,那么維護(hù)計數(shù)器阁猜,釋放內(nèi)存等等工作需要你手工來完成。
解決:一般是由類的靜態(tài)方法創(chuàng)建的, 函數(shù)名中不會出現(xiàn)alloc或init字樣, 如[NSString string]和[NSArray arrayWithObject:], 創(chuàng)建后引用計數(shù)+0, 在函數(shù)出棧后釋放, 即相當(dāng)于一個棧上的局部變量. 當(dāng)然也可以通過retain延長對象的生存期.
3). (NSAutoRealeasePool)內(nèi)存池:可以通過創(chuàng)建和釋放內(nèi)存池控制內(nèi)存申請和回收的時機(jī).
解決:是由autorelease加入系統(tǒng)內(nèi)存池, 內(nèi)存池是可以嵌套的, 每個內(nèi)存池都需要有一個創(chuàng)建釋放對, 就像main函數(shù)中寫的一樣. 使用也很簡單, 比如[[[NSString alloc]initialWithFormat:@”Hey you!”] autorelease], 即將一個NSString對象加入到最內(nèi)層的系統(tǒng)內(nèi)存池, 當(dāng)我們釋放這個內(nèi)存池時, 其中的對象都會被釋放.
9. 原子(atomic)跟非原子(non-atomic)屬性有什么區(qū)別?
答:
1). atomic提供多線程安全蹋艺。是防止在寫未完成的時候被另外一個線程讀取剃袍,造成數(shù)據(jù)錯誤
2). non-atomic:在自己管理內(nèi)存的環(huán)境中,解析的訪問器保留并自動釋放返回的值捎谨,如果指定了 nonatomic 民效,那么訪問器只是簡單地返回這個值憔维。
10. 看下面的程序,第一個NSLog會輸出什么?這時str的retainCount是多少?第二個和第三個呢? 為什么?
NSMutableArray* ary = [[NSMutableArray array] retain];
NSString *str = [NSString stringWithFormat:@"test"];
[str retain];
[aryaddObject:str];
NSLog(@”%@%d”,str,[str retainCount]);
[str retain];
[str release];
[str release];
NSLog(@”%@%d”,str,[str retainCount]);
[aryremoveAllObjects];
NSLog(@”%@%d”,str,[str retainCount]);
str的retainCount創(chuàng)建+1,retain+1畏邢,加入數(shù)組自動+1 3
retain+1业扒,release-1,release-1 2
數(shù)組刪除所有對象棵红,所有數(shù)組內(nèi)的對象自動-1 1
11. 內(nèi)存管理的幾條原則時什么?按照默認(rèn)法則.那些關(guān)鍵字生成的對象需要手動釋放?在和property結(jié)合的時候怎樣有效的避免內(nèi)存泄露?
答:誰申請凶赁,誰釋放
遵循Cocoa Touch的使用原則;
內(nèi)存管理主要要避免“過早釋放”和“內(nèi)存泄漏”咧栗,對于“過早釋放”需要注意@property設(shè)置特性時逆甜,一定要用對特性關(guān)鍵字,對于“內(nèi)存泄漏”致板,一定要申請了要負(fù)責(zé)釋放交煞,要細(xì)心。
關(guān)鍵字alloc 或new 生成的對象需要手動釋放;
設(shè)置正確的property屬性斟或,對于retain需要在合適的地方釋放素征,
12.如何對iOS設(shè)備進(jìn)行性能測試?
答: Profile-> Instruments ->Time Profiler
13. Object C中創(chuàng)建線程的方法是什么?如果在主線程中執(zhí)行代碼,方法是什么?如果想延時執(zhí)行代碼萝挤、方法又是什么?
答:線程創(chuàng)建有三種方法:使用NSThread創(chuàng)建御毅、使用GCD的dispatch、使用子類化的NSOperation,然后將其加入NSOperationQueue;在主線程執(zhí)行代碼怜珍,方法是performSelectorOnMainThread端蛆,如果想延時執(zhí)行代碼可以用performSelector:onThread:withObject:waitUntilDone:
14. MVC設(shè)計模式是什么? 你還熟悉什么設(shè)計模式酥泛?
答:
設(shè)計模式:并不是一種新技術(shù)今豆,而是一種編碼經(jīng)驗,使用比如java中的接口柔袁,iphone中的協(xié)議呆躲,繼承關(guān)系等基本手段,用比較成熟的邏輯去處理某一種類型的事情捶索,總結(jié)為所謂設(shè)計模式插掂。面向?qū)ο缶幊讨校琷ava已經(jīng)歸納了23種設(shè)計模式腥例。
mvc設(shè)計模式 :模型辅甥,視圖,控制器院崇,可以將整個應(yīng)用程序在思想上分成三大塊肆氓,對應(yīng)是的數(shù)據(jù)的存儲或處理,前臺的顯示底瓣,業(yè)務(wù)邏輯的控制谢揪。 Iphone本身的設(shè)計思想就是遵循mvc設(shè)計模式蕉陋。其不屬于23種設(shè)計模式范疇。
代理模式:代理模式給某一個對象提供一個代理對象拨扶,并由代理對象控制對源對象的引用.比如一個工廠生產(chǎn)了產(chǎn)品凳鬓,并不想直接賣給用戶,而是搞了很多代理商患民,用戶可以直接找代理商買東西缩举,代理商從工廠進(jìn)貨.常見的如QQ的自動回復(fù)就屬于代理攔截,代理模式在iphone中得到廣泛應(yīng)用.
單例模式:說白了就是一個類不通過alloc方式創(chuàng)建對象匹颤,而是用一個靜態(tài)方法返回這個類的對象仅孩。系統(tǒng)只需要擁有一個的全局對象,這樣有利于我們協(xié)調(diào)系統(tǒng)整體的行為印蓖,比如想獲得[UIApplication sharedApplication];任何地方調(diào)用都可以得到 UIApplication的對象辽慕,這個對象是全局唯一的。
觀察者模式: 當(dāng)一個物體發(fā)生變化時赦肃,會通知所有觀察這個物體的觀察者讓其做出反應(yīng)溅蛉。實(shí)現(xiàn)起來無非就是把所有觀察者的對象給這個物體,當(dāng)這個物體的發(fā)生改變他宛,就會調(diào)用遍歷所有觀察者的對象調(diào)用觀察者的方法從而達(dá)到通知觀察者的目的船侧。
工廠模式:
public class Factory{
public static Sample creator(int which){
if (which==1)
return new SampleA();
else if (which==2)
return new SampleB();
}
}
15 淺復(fù)制和深復(fù)制的區(qū)別?
答:淺層復(fù)制:只復(fù)制指向?qū)ο蟮闹羔槪粡?fù)制引用對象本身厅各。
深層復(fù)制:復(fù)制引用對象本身镜撩。
意思就是說我有個A對象,復(fù)制一份后得到A_copy對象后讯检,對于淺復(fù)制來說琐鲁,A和A_copy指向的是同一個內(nèi)存資源,復(fù)制的只不過是是一個指針人灼,對象本身資源
還是只有一份围段,那如果我們對A_copy執(zhí)行了修改操作,那么發(fā)現(xiàn)A引用的對象同樣被修改,這其實(shí)違背了我們復(fù)制拷貝的一個思想投放。深復(fù)制就好理解了,內(nèi)存中存在了
兩份獨(dú)立對象本身奈泪。
用網(wǎng)上一哥們通俗的話將就是:
淺復(fù)制好比你和你的影子,你完蛋灸芳,你的影子也完蛋
深復(fù)制好比你和你的克隆人涝桅,你完蛋,你的克隆人還活著烙样。
16. 類別的作用?繼承和類別在實(shí)現(xiàn)中有何區(qū)別?
答:category 可以在不獲悉冯遂,不改變原來代碼的情況下往里面添加新的方法,只能添加谒获,不能刪除修改蛤肌,并且如果類別和原來類中的方法產(chǎn)生名稱沖突壁却,則類別將覆蓋原來的方法,因為類別具有更高的優(yōu)先級裸准。
類別主要有3個作用:
1).將類的實(shí)現(xiàn)分散到多個不同文件或多個不同框架中展东。
2).創(chuàng)建對私有方法的前向引用。
3).向?qū)ο筇砑臃钦絽f(xié)議炒俱。
繼承可以增加盐肃,修改或者刪除方法,并且可以增加屬性权悟。
17. 類別和類擴(kuò)展的區(qū)別砸王。
答:category和extensions的不同在于 后者可以添加屬性。另外后者添加的方法是必須要實(shí)現(xiàn)的僵芹。
extensions可以認(rèn)為是一個私有的Category处硬。
18. oc中的協(xié)議和java中的接口概念有何不同?
答:OC中的代理有2層含義小槐,官方定義為 formal和informal protocol拇派。前者和Java接口一樣。
informal protocol中的方法屬于設(shè)計模式考慮范疇凿跳,不是必須實(shí)現(xiàn)的件豌,但是如果有實(shí)現(xiàn),就會改變類的屬性控嗜。
其實(shí)關(guān)于正式協(xié)議茧彤,類別和非正式協(xié)議我很早前學(xué)習(xí)的時候大致看過,也寫在了學(xué)習(xí)教程里
“非正式協(xié)議概念其實(shí)就是類別的另一種表達(dá)方式“這里有一些你可能希望實(shí)現(xiàn)的方法疆栏,你可以使用他們更好的完成工作”曾掂。
這個意思是,這些是可選的壁顶。比如我門要一個更好的方法珠洗,我們就會申明一個這樣的類別去實(shí)現(xiàn)。然后你在后期可以直接使用這些更好的方法若专。
這么看许蓖,總覺得類別這玩意兒有點(diǎn)像協(xié)議的可選協(xié)議〉魉ィ”
現(xiàn)在來看膊爪,其實(shí)protocal已經(jīng)開始對兩者都統(tǒng)一和規(guī)范起來操作,因為資料中說“非正式協(xié)議使用interface修飾“嚎莉,
現(xiàn)在我們看到協(xié)議中兩個修飾詞:“必須實(shí)現(xiàn)(@requied)”和“可選實(shí)現(xiàn)(@optional)”米酬。
19. 什么是KVO和KVC?
答:KVC:鍵 – 值編碼是一種間接訪問對象的屬性使用字符串來標(biāo)識屬性,而不是通過調(diào)用存取方法趋箩,直接或通過實(shí)例變量訪問的機(jī)制赃额。
很多情況下可以簡化程序代碼琼懊。apple文檔其實(shí)給了一個很好的例子。
KVO:鍵值觀察機(jī)制爬早,他提供了觀察某一屬性變化的方法哼丈,極大的簡化了代碼。
具體用看到嗯哼用到過的一個地方是對于按鈕點(diǎn)擊變化狀態(tài)的的監(jiān)控筛严。
比如我自定義的一個button
[self addObserver:self forKeyPath:@"highlighted" options:0 context:nil];
#pragma mark KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"highlighted"] ) {
[self setNeedsDisplay];
}
}
對于系統(tǒng)是根據(jù)keypath去取的到相應(yīng)的值發(fā)生改變醉旦,理論上來說是和kvc機(jī)制的道理是一樣的。
對于kvc機(jī)制如何通過key尋找到value:
“當(dāng)通過KVC調(diào)用對象時桨啃,比如:[self valueForKey:@”someKey”]時车胡,程序會自動試圖通過幾種不同的方式解析這個調(diào)用。首先查找對象是否帶有 someKey 這個方法照瘾,如果沒找到匈棘,會繼續(xù)查找對象是否帶有someKey這個實(shí)例變量(iVar),如果還沒有找到析命,程序會繼續(xù)試圖調(diào)用 -(id) valueForUndefinedKey:這個方法主卫。如果這個方法還是沒有被實(shí)現(xiàn)的話,程序會拋出一個NSUndefinedKeyException異常錯誤鹃愤。
(cocoachina.com注:Key-Value Coding查找方法的時候簇搅,不僅僅會查找someKey這個方法,還會查找getsomeKey這個方法软吐,前面加一個get瘩将,或者_(dá)someKey以及_getsomeKey這幾種形式。同時凹耙,查找實(shí)例變量的時候也會不僅僅查找someKey這個變量姿现,也會查找_someKey這個變量是否存在。)
設(shè)計valueForUndefinedKey:方法的主要目的是當(dāng)你使用-(id)valueForKey方法從對象中請求值時肖抱,對象能夠在錯誤發(fā)生前备典,有最后的機(jī)會響應(yīng)這個請求。這樣做有很多好處虐沥,下面的兩個例子說明了這樣做的好處熊经。“
來至cocoa欲险,這個說法應(yīng)該挺有道理镐依。
因為我們知道button卻是存在一個highlighted實(shí)例變量.因此為何上面我們只是add一個相關(guān)的keypath就行了,
可以按照kvc查找的邏輯理解天试,就說的過去了槐壳。
20. 代理的作用?
答:代理的目的是改變或傳遞控制鏈。允許一個類在某些特定時刻通知到其他類喜每,而不需要獲取到那些類的指針务唐■ㄈ粒可以減少框架復(fù)雜度。
另外一點(diǎn)枫笛,代理可以理解為java中的回調(diào)監(jiān)聽機(jī)制的一種類似吨灭。