- 相關(guān)推薦
iPhone軟件開發(fā)面試題
1.根據(jù)程序給出問題答案
main()
{
int a[5]={1,2,3,4,5};
int *ptr=(int *)(&a 1);
printf("%d,%d",*(a 1),*(ptr-1));
}
答:2,5
*(a 1)就是a[1],*(ptr-1)就是a[4],執(zhí)行結(jié)果是2,5
&a 1不是首地址 1,系統(tǒng)會認為加一個a數(shù)組的偏移,是偏移了一個數(shù)組的大小(本例是5個int)int *ptr=(int*)(&a 1);?
則ptr實際是&(a[5]),也就是a 5。原因如下:&a是數(shù)組指針,其類型為 int (*)[5],而指針加1要根據(jù)指針類型加上一定的值,不同類型的指針 1之后增加的大小不同。是長度為5的int數(shù)組指針,所以要加 5*sizeof(int),所以ptr實際是a[5]。但是prt與(&a 1)類型是不一樣的(這點很重要),所以prt-1只會減去sizeof(int*)。
a,&a的地址是一樣的,但意思不一樣。a是數(shù)組首地址,也就是a[0]的地址,&a是對象(數(shù)組)首地址,a 1是數(shù)組下一元素的地址,即a[1],&a 1是下一個對象的地址,即a[5].
2.以下為Windows NT下的32位C 程序,請計算sizeof的值??
void Func ( char str[100] ) ?
{ ?
sizeof( str ) =? ?
} ?
void *p = malloc(100 ); ?
sizeof ( p ) = ?
這題很常見了,Func ( char str[100] )函數(shù)中數(shù)組名作為函數(shù)形參時,在函數(shù)體內(nèi),數(shù)組名失去了本身的內(nèi)涵,僅僅只是一個指針;在失去其內(nèi)涵的同時,它還失去了其常量特性,可以作自增、自減等操作,可以被修改。Windows NT 32位平臺下,指針的長度(占用內(nèi)存的大小)為4字節(jié),故sizeof( str ) 、sizeof ( p ) 都為4。
3.還是考指針,不過我對cocoa的代碼還是不太熟悉
大概是這樣的
- (void)*getNSString(const NSString *inputString)
{
inputString =@"This is a main test\n";
return ;
}
main(void)
{
NSString*a=@"Main";
NSString *aString= [NSString stringWithString:@"%@",getNSString(a)];
NSLog(@"%@\n", aString);
}
最后問輸出的字符串:NULL,output在函數(shù)返回后,內(nèi)存已經(jīng)被釋放。
4.用預(yù)處理指令#define聲 明一個常數(shù),用以表明1年中有多少秒(忽略閏年問題)
#define SECONDS_PER_YEAR (60 * 60 * 24 *365)UL ?
我在這想看到幾件事 情:
#define 語法的基本知識(例如:不能以分號結(jié)束,括號的使用,等等) ?
懂得預(yù)處理器將為你計算常數(shù)表達式的值,因此,直接寫出你是如何計算一年中有多少秒而不是計算出實際的值,是更清晰而沒有代價的。
意識到這個表達式將使一個16位機的整型數(shù)溢出-因此要用到長整型符號L,告訴編譯器這個常數(shù)是的長整型數(shù)。
如果你在你的表達式中用到UL(表示無符號長整型),那么你有了一個好的起點。記住,第一印象很重要。
5.寫一個"標(biāo)準"宏MIN ,這個宏輸入兩個參數(shù)并返回較小的一個。
?#define MIN(A,B) ((A) <= (B) ? (A) : (B))
這個測試是為下面的目的而設(shè)的:
標(biāo)識#define在宏中應(yīng)用的基本知識。這是很重要的,因為直到嵌入(inline)操作符變?yōu)闃?biāo)準C的一部分,宏是方便產(chǎn)生嵌入代碼的唯一方法,對于嵌入式系統(tǒng)來說,為了能達到要求的性能,嵌入代碼經(jīng)常是必須的方法。
三重條件操作符的知識。這個操作符存在C語言中的原因是它使得編譯器能產(chǎn)生比 if-then-else
更優(yōu)化的代碼,了解這個用法是很重要的。
懂得在宏中小心地把參數(shù)用括號括起來
我也用這個問題開始討論宏的副作用,例如:當(dāng)你寫下面的代碼時會發(fā)生什么事?
least = MIN(*p , b);
結(jié)果是:((*p ) <= (b) ? (*p ) : (*p ))這個表達式會產(chǎn)生副作用,指針p會作三次 自增操作。
6.寫一個委托的 interface
@protocol MyDelegate;
@interface MyClass: NSObject
{
id
}
// 委托方法
@protocol MyDelegate
- (void)didJobs:(NSArray *)args;
@end
7. 寫一個NSString類的實現(xiàn)
(id)initWithCString:(constchar *)nullTerminatedCString encoding:(NSStringEncoding)encoding;
(id) stringWithCString: (constchar*)nullTerminatedCString ? encoding: (NSStringEncoding)encoding?
{?
NSString *obj;
obj= [self allocWithZone: NSDefaultMallocZone()];
obj = [objinitWithCString: nullTerminatedCString encoding: encoding];
returnAUTORELEASE(obj);?
}
8.obj-c有多重繼承么?不是的話有什么替代方法?
?cocoa 中所有的類都是NSObject的子類,多繼承在這里是用protocol委托代理來實現(xiàn)的。
9.obj- c有私有方法么?私有變量呢
objective-c 類里面的方法只有兩種, 靜態(tài)方法和實例方法. 這似乎就不是完整的面向?qū)ο罅?按照OOP的原則就是一個對象只暴露有用的東西. 如果沒有了私有方法的話, 對于一些小范圍的代碼重用就不那么順手了. 在類里面聲名一個私有方法
@interface Controller : NSObject { NSString*something; }
(void)thisIsAStaticMethod;
- (void)thisIsAnInstanceMethod;
@end
@interface Controller (private) -
(void)thisIsAPrivateMethod;
@end
@private可以用來修飾私有變量
在Objective‐C中,所有實例變量默認都是私有的,所有實例方法默認都是公有的
10.關(guān)鍵字const有什么含意?修飾類呢?static的作 用,用于類呢?還有extern c的作用
、 const 意味著"只讀",下面的聲明都是什么意思:
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前兩個的作用是一樣,a是一個常整型數(shù)。第三個意味著a是一個指向常整型數(shù)的指針(也就是整型數(shù)是不可修改的,但指針可以)。第四個意思a是一個指向整型數(shù)的常指針(也就是說,指針指向的整型數(shù)是可以修改的,但指針是不可修改 的)。最后一個意味著a是一個指向常整型數(shù)的常指針(也就是說,指針指向的整型數(shù)是不可修改的,同時指針也是不可修改的)。
結(jié)論:
關(guān)鍵字const的作用是為給讀你代碼的人傳達非常有用的信息,實際上,聲明一個參數(shù)為常量是為了告訴了用戶這個參數(shù)的應(yīng)用目的。如果你曾花很多時間清理其它人留下的垃圾,你就會很快學(xué)會感謝這點多余的信息。(當(dāng)然,懂得用const的程序員很少會留下的垃圾讓別人來清理的。)
通過給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。
合理地使用關(guān)鍵字const可以使編譯器很自然地保護那些不希望被改變的參數(shù),防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現(xiàn)。 ?
(1)欲阻止一個變量被改變,可以使用const 關(guān)鍵字。在定義該const變量時,通常需要對它進行初始化,因為以后就沒有機會再去改變它了;
(2)對指針來說,可以指定指針本身為 const,也可以指定指針?biāo)傅臄?shù)據(jù)為 const,或二者同時指?定為 const;
(3)在一個函數(shù)聲明中,const 可以修飾形參,表明它是一個輸入?yún)?shù),在函數(shù)內(nèi)部不能改變其值;
(4)對于類的成員函數(shù),若指定其為 const 類型,則表明其是一個常函數(shù),不能修改類的成員變量;
(5)對于類的成員函數(shù),有時候必須指定其返回值為 const 類型,以使得其返回值不為“左值”。
、 static 關(guān)鍵字的作用:
(1)函數(shù)體內(nèi) static 變量的作用范圍為該函數(shù)體,不同于 auto 變量,該變量的內(nèi)存只被分配一次,?因此其值在下次調(diào)用時仍維持上次的值;
(2)在模塊內(nèi)的 static 全局變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問;
(3)在模塊內(nèi)的 static 函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用,這個函數(shù)的使用范圍被限制在聲明?它的模塊內(nèi);
(4)在類中的 static 成員變量屬于整個類所擁有,對類的所有對象只有一份拷貝;
(5)在類中的 static 成員函數(shù)屬于整個類所擁有,這個函數(shù)不接收 this 指針,因而只能訪問類的static 成員變量。
、 extern "C" 的作用
(1)被 extern"C"限定的函數(shù)或變量是 extern 類型的;
extern 是 C/C 語言中表明函數(shù)和全局變量作用范圍(可見性)的關(guān)鍵字,該關(guān)鍵字告訴編譯器,其聲明的函數(shù)和變量可以在本模塊或其它模塊中使用。
(2)被 extern"C"修飾的變量和函數(shù)是按照 C 語言方式編譯和連接的;
extern "C"的慣用法
(1)在 C 中引用 C 語言中的函數(shù)和變量,在包含 C 語言頭文件(假設(shè)為 cExample.h)時,需進?行下列處理: ?extern"C" ?{ ?#include"cExample.h" ?} ?而在 C 語言的頭文件中,對其外部函數(shù)只能指定為 extern 類型,C 語言中不支持 extern "C"聲明,?在.c 文件中包含了 extern "C"時會出現(xiàn)編譯語法錯誤。
(2)在 C 中引用 C 語言中的函數(shù)和變量時,C 的頭文件需添加 extern "C",但是在 C 語言中不?能直接引用聲明了extern "C"的該頭文件,應(yīng)該僅將 C 文件中將 C 中定義的 extern "C"函數(shù)聲明為?extern 類型。
11.關(guān)鍵字volatile有什么含意?并給出三個不同的例子。
一個定義為 volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設(shè)這個變量的值了。精確地說就是,優(yōu)化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。
下面是volatile變量的幾個例子:
并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)
一個中斷服務(wù)子程序中會訪問到的非自動變量(Non-automatic variables)
多線程應(yīng)用中被幾個任務(wù)共享的變量
12.一個參數(shù)既可以是const還可以是volatile嗎?解釋為什么。一個指針可以是volatile 嗎?解釋為什么。
下面是答案:
一個例子是只讀的狀態(tài)寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應(yīng)該試圖去修改它。
盡管這并不很常見。一個例子是當(dāng)一個中服務(wù)子程序修該一個指向一個buffer的指針時。
13.為什么標(biāo)準頭文件都有類似以下的結(jié)構(gòu)?
#ifndef __INCvxWorksh
#define __INCvxWorksh
#ifdef __cplusplus
extern "C"
{
#endif
/*...*/
#ifdef__cplusplus
}
#endif
#endif /* __INCvxWorksh */
顯然,頭文件中的編譯宏 “#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用是防止該頭文件被重復(fù)引用。
14.#import 跟#include的區(qū)別,@class呢?
@class一般用于頭文件中需要聲明該類的某個實例變量的時候用到,在m文件中還是需要使用#import
而#import比起#include的好處就是不會引起交叉編譯
15.MVC 模式的理解
MVC設(shè)計模式考慮三種對象:模型對象、視圖對象和控制器對象。
模型對象代表特別的知識和專業(yè)技能,它們負責(zé)保有應(yīng)用程序的數(shù)據(jù)和定義操作數(shù)據(jù)的邏輯。
視圖對象知道如何顯示應(yīng)用程序的模型數(shù)據(jù),而且可能允許用戶對其進行編輯。
控制器對象是應(yīng)用程序的視圖對象和模型對象之間的協(xié)調(diào)者。
16. 線程與進程的區(qū)別和聯(lián)系?
進程和線程都是由操作系統(tǒng)所體會的程序運行的基本單元,系統(tǒng)利用該基本單元實現(xiàn)系統(tǒng)對應(yīng)用的并發(fā)性。
進程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產(chǎn)生影響,而線程只是一個進程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對于一些要求同時進行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進程。
17.列舉幾種進程的同步機制,并比較其優(yōu)缺點。
答案:原子操作;信號量機制;自旋鎖;管程;會合;分布式系統(tǒng) ?
18.進程之間通信的途徑
答案:共享存儲系統(tǒng)消息傳遞系統(tǒng)管道,以文件系統(tǒng)為基礎(chǔ) ?
19.進程死鎖的原因
答案:資源競爭及進程推進順序非法 ?
20.死鎖的4個必要條件
答案:互斥;請求保持;不可剝奪;環(huán)路 ?
21.死鎖的處理
答案:鴕鳥策略;預(yù)防策略;避免策略;檢測與解除死鎖
22.堆和棧的區(qū)別
管理方式:對于棧來講,是由編譯器自動管理,無需我們手工控制;對于堆來說,釋放工作由程序員控制,容易產(chǎn)生memory leak。
申請大。 棧:在Windows下,棧是向低地址擴展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域。這句話的意思是棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數(shù)),如果申請的空間超過棧的剩余空間時,將提示 overflow。因此,能從棧獲得的空間較小。?堆:堆是向高地址擴展的數(shù)據(jù)結(jié)構(gòu),是不連續(xù)的內(nèi)存區(qū)域。這是由于系統(tǒng)是用鏈表來存儲的空閑內(nèi)存地址的,自然是不連續(xù)的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限于計算機系統(tǒng)中有效的虛擬內(nèi)存。由此可見,堆獲得的空間比較靈活,也比較大。
碎片問題:對于堆來講,頻繁的new/delete勢必會造成內(nèi)存空間的不連續(xù),從而造成大量的碎片,使程序效率降低。對于棧來講,則不會存在這個問題,因為棧是先進后出的隊列,他們是如此的一一對應(yīng),以至于永遠都不可能有一個內(nèi)存塊從棧中間彈出。
分配方式:堆都是動態(tài)分配的,沒有靜態(tài)分配的堆。棧有2種分配方式:靜態(tài)分配和動態(tài)分配。靜態(tài)分配是編譯器完成的,比如局部變量的分配。動態(tài)分配由 alloca函數(shù)進行分配,但是棧的動態(tài)分配和堆是不同的,他的動態(tài)分配是由編譯器進行釋放,無需我們手工實現(xiàn)。
分配效率:棧是機器系統(tǒng)提 供的數(shù)據(jù)結(jié)構(gòu),計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執(zhí)行,這就決定了棧的效率比較高。堆則是C/C 函數(shù)庫提供的,它的機制是很復(fù)雜的。
23.什么是鍵-值,鍵路徑是什么
模型的性質(zhì)是通過一個簡單的鍵(通常是個字符串)來指定的。視圖和控制器通過鍵 來查找相應(yīng)的屬性值。在一個給定的實體中,同一個屬性的所有值具有相同的數(shù)據(jù)類型。鍵-值編碼技術(shù)用于進行這樣的查找—它是一種間接訪問對象屬性的機制。
鍵路徑是一個由用點作分隔符的鍵組成的字符串,用于指定一個連接在一起的對象性 質(zhì)序列。第一個鍵的性質(zhì)是由先前的性質(zhì)決定的,接下來每個鍵的值也是相對于其前面的性質(zhì)。鍵路徑使您可以以獨立于模型?實現(xiàn)的方式指定相關(guān)對象的性質(zhì)。通過鍵路徑,您可以指定對象圖中的一個任意深度的路徑,使其指向相關(guān)對象的特定屬性。
For example, the key path address.streetwouldget the value of the address property from the receiving
object, and then determine the streetproperty relative to the address object.
24.c和obj-c 如何混用
1)obj-c的編譯器處理 后綴為m的文件時,可以識別obj-c和c的代碼, 處理mm文件可以識別obj-c,c,c 代碼,但cpp文件必須只能用c/c 代碼,而且cpp文件include的頭文件中,也不能出現(xiàn)obj- c的代碼,因為cpp只是cpp?
2) 在mm文件中混用cpp直接使用即可,所以obj-c混cpp不是問題?
3)在cpp中混用obj- c其實就是使用obj-c編寫的模塊是我們想要的。?
如果模塊以類實現(xiàn),那么要按照cpp class的標(biāo)準寫類的定義,頭文件中不能出現(xiàn)obj-c的東西,包括#import cocoa的。實現(xiàn)文件中,即類的實現(xiàn)代碼中可以使用obj-c的東西,可以import,只是后綴是mm。?如果模塊以函數(shù)實現(xiàn),那么頭文件要按 c的格式聲明函數(shù),實現(xiàn)文件中,c 函數(shù)內(nèi)部可以用obj-c,但后綴還是mm或m。
總結(jié):只要cpp文件和cppinclude的文件中不包含obj-c的東西就可以用了,cpp混用obj-c的關(guān)鍵是使用接口,而不能直接使用實現(xiàn)代碼,實際上cpp混用的是 obj-c編譯后的o文件,這個東西其實是無差別的,所以可以用。obj-c的編譯器支持cpp.
25.目標(biāo)-動作機制
目標(biāo)是動作消息的接收者。一個控件,或者更為常見的是它的單元,以插座變量(參 見"插座變量"部分)的形式保有其動作消息的目標(biāo)。
動作是控件發(fā)送給目標(biāo)的消息,或者從目標(biāo)的角度看,它是目標(biāo)為了響應(yīng)動作而實現(xiàn)的方法。
程序需要某些機制來進行事件和指令的翻譯。這個機制就是目標(biāo)-動作機制。
26.cocoa touch框架
iPhoneOS 應(yīng)用程序的基礎(chǔ) Cocoa Touch 框架重用了許多 Mac 系統(tǒng)的成熟模式,但是它更多地專注于觸摸的接口和優(yōu)化。UIKit 為您提供了在 iPhone OS 上實現(xiàn)圖形,事件驅(qū)動程序的基本工具,其建立在和 Mac OS X 中一樣的Foundation 框架上,包括文件處理,網(wǎng)絡(luò),字符串操作等。
CocoaTouch 具有和 iPhone 用戶接口一致的特殊設(shè)計。有了 UIKit,您可以使用 iPhone OS 上的獨特的圖形接口控件,按鈕,以及全屏視圖的功能,您還可以使用加速儀和多點觸摸手勢來控制您的應(yīng)用。
各色俱全的框架 除了 UIKit 外,Cocoa Touch 包含了創(chuàng)建世界一流 iPhone 應(yīng)用程序需要的所有框架,從三維圖形,到專業(yè)音效,甚至提供設(shè)備訪問 API 以控制攝像頭,或通過 GPS 獲知當(dāng)前位置。Cocoa Touch 既包含只需要幾行代碼就可以完成全部任務(wù)的強大的 Objective-C 框架,也在需要時提供基礎(chǔ)的 C 語言 API 來直接訪問系統(tǒng)。這些框架包括:
Core Animation
通過 Core Animation,您就可以通過一個基于組合獨立圖層的簡單的編程模型來創(chuàng)建豐富的用戶體驗。
Core Audio
Core Audio 是播放,處理和錄制音頻的專業(yè)技術(shù),能夠輕松為您的應(yīng)用程序添加強大的音頻功能。
Core Data
提供了一個面向?qū)ο蟮臄?shù)據(jù)管理解決方案,它易于使用和理解,甚至可處理任何應(yīng)用 或大或小的數(shù)據(jù)模型。
功能列表:框架分類
下面是 Cocoa Touch 中一小部分可用的框架:
音頻和視頻
Core Audio
OpenAL
Media Library
AV Foundation
數(shù)據(jù)管理
Core Data
SQLite
圖形和動畫
Core Animation
OpenGL ES
Quartz 2D
網(wǎng)絡(luò)/li>
Bonjour
WebKit
BSD Sockets
用戶應(yīng)用
Address Book
Core Location
Map Kit
Store Kit
27.objc的內(nèi)存管理
如果您通過分配和初始化(比如[[MyClass alloc] init])的方式來創(chuàng)建對象,您就擁有這個對象,需要負責(zé)該對象的釋放。這個規(guī)則在使用NSObject的便利方法new 時也同樣適用。
如果您拷貝一個對象,您也擁有拷貝得到的對象,需要負責(zé)該對象的釋放。
如果您保持一個對象,您就部分擁有這個對象,需要在不再使用時釋放該對象。
反過來,如果您從其它對象那里接收到一個對象,則您不擁有該對象,也不應(yīng)該釋放它(這個規(guī)則有少數(shù)的例外,在參考文檔中有顯式的說明)。
28.自動釋放池是什么,如何工作
當(dāng)您向一個對象發(fā)送一個autorelease消息時,Cocoa就會將該對象的一個引用放入到最新的自動釋放池。它仍然是個正當(dāng)?shù)膶ο螅虼俗詣俞尫懦囟x的作用域內(nèi)的其它對象可以向它發(fā)送消息。當(dāng)程序執(zhí)行到作用域結(jié)束的位置時,自動釋放池就會被釋放,池中的所有對象也就被釋放。
1. ojc-c 是通過一種"referring counting"(引用計數(shù))的方式來管理內(nèi)存的, 對象在開始分配內(nèi)存(alloc)的時候引用計數(shù)為一,以后每當(dāng)碰到有copy,retain的時候引用計數(shù)都會加一, 每當(dāng)碰到release和autorelease的時候引用計數(shù)就會減一,如果此對象的計數(shù)變?yōu)榱?, 就會被系統(tǒng)銷毀.?2. NSAutoreleasePool 就是用來做引用計數(shù)的管理工作的,這個東西一般不用你管的.?
3. autorelease和release沒什么區(qū)別,只是引用計數(shù)減一的時機不同而已,autorelease會在對象的使用真正結(jié)束的時候才做引用計數(shù)減一.
29.類工廠方法是什么
類工廠方法的實現(xiàn)是為了向客戶提供方便,它們將分配和初始化合在一個步驟中,返回被創(chuàng)建的對象,并進行自動釋放處理。這些方法的形式是 (type)className...(其中 className不包括任何前綴)。
工廠方法可能不僅僅為了方便使用。它們不但可以將分配和初始化合在一起,還可以為初始化過程提供對象的分配信息。
類工廠方法的另一個目的是使類(比如NSWorkspace)提供單件實例。雖然init...方法可以確認一個類在每次程序運行過程只存在一個實例,但它需要首先分配一個“生的”實例,然后還必須釋放該實例。工廠方法則可以避免為可能沒有用的對象盲目分配內(nèi)存。
30.單件實例是什么
Foundation和 Application Kit 框架中的一些類只允許創(chuàng)建單件對象,即這些類在當(dāng)前進程中的唯一實例。舉例來說,NSFileManager 和NSWorkspace 類在使用時都是基于進程進行單件對象的實例化。當(dāng)向這些類請求實例的時候,它們會向您傳遞單一實例的一個引用,如果該實例還不存在,則首先進行實例的分配和初始化。 單件對象充當(dāng)控制中心的角色,負責(zé)指引或協(xié)調(diào)類的各種服務(wù)。如果類在概念上只有一個實例(比如NSWorkspace),就應(yīng)該產(chǎn)生一個單件實例,而不是多個實例;如果將來某一天可能有多個實例,您可以使用單件實例機制,而不是工廠方法或函數(shù)。
31.動態(tài)綁定
在運行時確定要調(diào)用的方法,動態(tài)綁定將調(diào)用方法的確定也推遲到運行時。在編譯時,方法的調(diào)用并不和代碼綁定在一起,只有在消息發(fā)送出來之后,才確定被調(diào)用的代碼。通過動態(tài)類型和動態(tài)綁定技術(shù),您的代碼每次執(zhí)行都可以得到不同的結(jié)果。運行時因子負責(zé)確定消息的接收者和被調(diào)用的方法。運行時的消息分發(fā)機制為動態(tài)綁定提供支持。當(dāng)您向一個動態(tài)類型確定了的對象發(fā)送消息時,運行環(huán)境系統(tǒng)會通過接收者的isa指針定位對象的類,并以此為起點確定被調(diào)用的方法,方法和消息是動態(tài)綁定的。而且,您不必在Objective-C 代碼中做任何工作,就可以自動獲取動態(tài)綁定的好處。您在每次發(fā)送消息時,特別是當(dāng)消息的接收者是動態(tài)類型已經(jīng)確定的對象時,動態(tài)綁定就會例行而透明地發(fā)生。
32.obj-c 的優(yōu)缺點
Obj-c優(yōu)點:
1) Cateogies
2) Posing
3) 動態(tài)識別
4) 指標(biāo)計算
5) 彈性訊息傳遞
6) 不是一個過度復(fù)雜的 C 衍生語言
7) Objective-C 與 C 可混合編程?
Obj-c缺點:
1)不支持命名空間
2)不支持運算符重載
3)不支持多重繼承
4)使用動態(tài)運行時類型,所有的方法都是函數(shù)調(diào)用,所以很多編譯時優(yōu)化方法都用不到。(如內(nèi)聯(lián)函數(shù)等),性能低劣。
33.sprintf,strcpy,memcpy使用上有什么要注意的地方
strcpy是一個字符串拷貝的函數(shù),它的函數(shù)原型為strcpy(char *dst, const char *src);
將 src開始的一段字符串拷貝到dst開始的內(nèi)存中去,結(jié)束的標(biāo)志符號為 '\0',由于拷貝的長度不是由我們自己控制的,所以這個字符串拷貝很容易出錯。具備字符串拷貝功能的函數(shù)有memcpy,這是一個內(nèi)存拷貝函數(shù),它的函數(shù)原型為memcpy(char *dst,const char* src, unsigned int len);
將長度為len的一段內(nèi)存,從src拷貝到dst中去,這個函數(shù)的長度可控。但是會有內(nèi)存疊加的問題。
sprintf是格式化函數(shù)。將一段數(shù)據(jù)通過特定的格式,格式化到一個字符串緩沖區(qū)中去。sprintf格式化的函數(shù)的長度不可控,有可能格式化后的字符串會超出緩沖區(qū)的大小,造成溢出。
34. 用變量a給出下面的定義
a)一個整型數(shù)(An integer)
b)一個指向整型數(shù)的指針( A pointer to an integer)
c)一個指向指針的的指針,它指向的指針是指向一個整型數(shù)( A pointer to a pointer to an intege)r
d)一個有10個整型數(shù)的數(shù)組( An array of 10 integers)
e)一個有10個指針的數(shù)組,該指針是指向一個整型數(shù)的。(An array of 10 pointers to integers)
f)一個指向有10個整型數(shù)數(shù)組的指針( A pointer to an array of 10 integers)
g)一個指向函數(shù)的指針,該函數(shù)有一個整型參數(shù)并返回一個整型數(shù)(A pointer to a function that takes an integer as anargument? and returns an integer)
h)一個有10個指針的數(shù)組,該指針指向一個函數(shù),該函數(shù)有一個整型參數(shù)并返回一個整型數(shù)( An array of ten pointersto functions t?hat take an integer argument and returnan integer ) ? ?
答案:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers tofunctions that take an integer argument and return an integer
35.readwrite ,readonly ,assign ,retain ,copy,nonatomic 屬性的作用
@property是 一個屬性訪問聲明,擴號內(nèi)支持以下幾個屬性:
1、getter=getterName,setter=setterName,設(shè)置setter與 getter的方法名
2、readwrite,readonly,設(shè)置可供訪問級別
3、assign,setter方法直接賦值,不進行 任何retain操作,為了解決原類型與環(huán)循引用問題
4、retain,setter方法對參數(shù)進行release舊值再retain新值,所有 實現(xiàn)都是這個順序(CC上有相關(guān)資料)
5、copy,setter方法進行Copy操作,與retain處理流程一樣,先舊值release,再 Copy出新的對象,retainCount為1。這是為了減少對上下文的依賴而引入的機制。
6、nonatomic,非原子性訪問,不加同步,多線程并發(fā)訪問會提高性能。注意,如果不加此屬性,則默認是兩個訪問方法都為原子型事務(wù)訪問。鎖被加到所屬對象實例級(我是這么理解的...)。?@synthesize xxx; 來實現(xiàn)實際代碼
36.ObjC中,與alloc語義相反的方法是dealloc還是release?與retain語義相反的方法是dealloc還是release,為什么?需要與alloc配對使用的方法是dealloc還是release,為什么?
答:alloc與dealloc語意相反,alloc是創(chuàng)建變量,dealloc是釋放變量。 retain 對應(yīng)release,retain 保留一個對象。調(diào)用之后,變量的計數(shù)加1;蛟S不是很明顯,
在這有例為證:
- (void) setName: (NSString*) name {
[name retain];
[myname release];
myname = name;
}
我們來解釋一下:設(shè)想,用戶在調(diào)用這個函數(shù)的時候,他注意了內(nèi)存的管理,所以他小心的寫了如下代碼:
NSString * newname = [[NSString alloc] initWithString: @"John"];
[aClass setName: newname];
[newname release];
我們來看一看newname的計數(shù)是怎么變化的。首先,它被alloc,count = 1; 然后,在setName中,它被retain, count = 2; 最后,用戶自己釋放newname,count = 1,myname指向了newname。這也解釋了為什么需要調(diào)用[myname release]。我們需要在給myname賦新值的時候,釋放掉以前老的變量。retain 之后直接dealloc對象計數(shù)器沒有釋放。alloc 需要與release配對使用,因為alloc 這個函數(shù)調(diào)用之后,變量的計數(shù)加1。所以在調(diào)用alloc 之后,一定要調(diào)用對應(yīng)的release。另外,在release一個變量之后,他的值仍然有效,所以最好是后面緊接著再var = nil。
37.什么是retaincount?
答:引用計數(shù)(refcount或者retain count)。對象的內(nèi)部保存一個數(shù)字,表示被引用的次數(shù)。例如,某個對象被兩個指針?biāo)赶?引用)那么它的retain count為2。需要銷毀對象的時候,不直接調(diào)用dealloc,而是調(diào)用release。release會讓retain count減1,只有retaincount等于0,系統(tǒng)才會調(diào)用dealloc真正銷毀這個對象。
38.以下每行代碼執(zhí)行后,person對象的retain count分別是多少
Person *person =[[Person alloc] init]; count 1
[person retain]; count 2
[person release];count 1
[person release];retain count = 1;
39.為什么很多內(nèi)置類如UITableViewController的delegate屬性都是assign而不是retain的?
答:會引起循環(huán)引用。
40.定義屬性時,什么情況使用copy,assign ,和retain
答:assign用于簡單數(shù)據(jù)類型,如NSInteger,double,bool,retain 和copy用戶對象,copy用于當(dāng) a指向一個對象,b也想指向同樣的對象的時候,如果用assign,a如果釋放,再調(diào)用b會crash,如果用copy 的方式,a和b各自有自己的內(nèi)存,就可以解決這個問題。retain 會使計數(shù)器加一,也可以解決assign的問題。另外:atomic和nonatomic用來決定編譯器生成的getter和setter是否為原子操作。在多線程環(huán)境下,原子操作是必要的,否則有可能引起錯誤的結(jié)果。加了atomic,setter函數(shù)會變成下面這樣:
if (property != newValue)
{
[property release];
property = [newValue retain];
}
41.對象是在什么時候被release的?
答:autorelease實際上只是把對release的調(diào)用延遲了,對于每一個Autorelease,系統(tǒng)只是把該Object放入了當(dāng)前的Autorelease pool中,當(dāng)該pool被釋放時,該pool中的所有Object會被調(diào)用Release。對于每一個Runloop,系統(tǒng)會隱式創(chuàng)建一個Autorelease pool,這樣所有的release pool會構(gòu)成一個象CallStack一樣的一個棧式結(jié)構(gòu),在每一個Runloop結(jié)束時,當(dāng)前棧頂?shù)腁utorelease pool會被銷毀,這樣這個pool里的每個Object(就是autorelease的對象)會被release。那什么是一個Runloop呢?一個UI事件,Timer call, delegate call, 都會是一個新的Runloop。
42.這段代碼有什么問題,如何修改
for (int i = 0; i
{
NSString *string = @”Abc”;
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@“%@”, string);
}
答:會內(nèi)存泄露,
for(int i = 0; i<1000;i ){
NSAutoreleasePool * pool1 = [[NSAutoreleasePool alloc] init];
NSString *string = @"Abc";
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@"%@",string);
[pool1 drain];
}
43.autorelease和垃圾回收機制(gc)有什么關(guān)系?
44.IPhone OS有沒有垃圾回收(gc)?
答:沒有。
45.什么是Notification?
答:觀察者模式,controller向defaultNotificationCenter添加自己的notification,其他類注冊這個notification就可以收到通知,這些類可以在收到通知時做自己的操作(多觀察者默認隨機順序發(fā)通知給觀察者們,而且每個觀察者都要等當(dāng)前的某個觀察者的操作做完才能輪到他來操作,可以用NotificationQueue的方式安排觀察者的反應(yīng)順序,也可以在添加觀察者中設(shè)定反映時間,取消觀察需要在viewDidUnload 跟dealloc中都要注銷)。參考鏈接:http://useyourloaf.com/blog/2010/6/6/delegation-or-notification.html
46.什么時候用delegate,什么時候用Notification?
答:delegate針對one-to-one關(guān)系,并且reciever可以返回值給sender,notification 可以針對one-to-one/many/none,reciever無法返回值給sender.所以,delegate用于sender希望接受到reciever的某個功能反饋值,notification用于通知多個object某個事件。
47.什么是KVC和KVO?
答:KVC(Key-Value-Coding)內(nèi)部的實現(xiàn):一個對象在調(diào)用setValue的時候,(1)首先根據(jù)方法名找到運行方法的時候所需要的環(huán)境參數(shù)。(2)他會從自己isa指針結(jié)合環(huán)境參數(shù),找到具體的方法實現(xiàn)的接口。(3)再直接查找得來的具體的方法實現(xiàn)。
KVO(Key-Value-Observing):當(dāng)觀察者為一個對象的屬性進行了注冊,被觀察對象的isa指針被修改的時候,isa指針就會指向一個中間類,而不是真實的類。所以isa指針其實不需要指向?qū)嵗龑ο笳鎸嵉念悺K晕覀兊某绦蜃詈貌灰蕾囉趇sa指針。在調(diào)用類的方法的時候,最好要明確對象實例的類名。
48.Notification和KVO有什么不同?
49.KVO在ObjC中是怎么實現(xiàn)的?
50.ViewController 的 loadView,viewDidLoad, viewDidUnload 分別是在什么時候調(diào)用的?在自定義ViewController的時候這幾個函數(shù)里面應(yīng)該做什么工作?
答:viewDidLoad在view 從nib文件初始化時調(diào)用,loadView在controller的view為nil時調(diào)用。此方法在編程實現(xiàn)view時調(diào)用,view 控制器默認會注冊memory warning notification,當(dāng)view controller的任何view 沒有用的時候,viewDidUnload會被調(diào)用,在這里實現(xiàn)將retain 的view release,如果是retain的IBOutlet view 屬性則不要在這里release,IBOutlet會負責(zé)release 。
51.ViewController 的 didReceiveMemoryWarning 是在什么時候被調(diào)用的?默認的操作是什么?
答:默認調(diào)用[superdidReceiveMemoryWarning]
http://m.ardmore-hotel.com/【iPhone軟件開發(fā)面試題】相關(guān)文章:
硅谷面試題精選02-03
Java經(jīng)典面試題12-29
Cisco的面試題09-25
Java面試題01-22
面試題及答案02-06
電信面試題07-20
IBM經(jīng)典面試題07-29
微軟面試題02-16
軟件開發(fā)口號11-21
軟件開發(fā)心得11-17