來自:伊甸網java
@ios
看到這個關鍵字,咱們就應該想到,這是Object-C對C語言的擴展,例如@interface XXX。c++
@interface程序員
聲明類web
@implementation面試
實現類objective-c
@protocol算法
聲明協議sql
@optional
與@protocol配合使用,說明協議中的某個或者某幾個方法能夠不實現
@required
與@protocol配合使用,說明協議中的某個方法或者某幾個方法必須實現
@end
與@interface ,@implementation,@protocol配合使用,表明聲明或者實現結束
@encode
@encode爲編譯器宏,它能夠將類型轉換爲相應的字符串(const char *)。
id
id是指向Objective-C類對象的指針,它能夠聲明爲任何類對象的指針,當在Objective-C中使用id時,編譯器會假定你知道id指向哪一個類的對象。與void*是不一樣的是,void*編譯器不知道也不假定指向任何類型的指針。
nil
定義爲一個常量,若是一個指針的值爲nil,表明這個指針沒有指向任何對象。
self
在Objective-C中,關鍵字self與c++中this是同一律念,就是類對象自身的地址,經過self能夠調用本身的實例變量和方法
Super
當子類須要調用父類的方法時,會用到Super關鍵字. Super指向的是父類的指針,子類重寫父類的方法時,調用父類的方法是一個比較好的習慣。由於當咱們不知道父類在該方法中實現的功能時,若是不調用父類的方法,有可能咱們重寫的方法會失去該功能,這是咱們不肯意看到的狀況。
NSNull
NSNull是沒有的意思,若是一個字典的值爲NSNull,那說明與該值對應的Key是沒有值的,例如Key爲address,說明與address對應的是值是沒有。
self super class public protected private id
[self class] [super class] selector
objective-c runtime reference
標準用法
self = [super init]
new
1 Objective-C有一個特性,就是能夠把類當成對象來發送消息,這種用法一般用於新建對像時,例如 XXX *object = [XXX new];
類方法 +
若是想聲明屬於類而不屬於類對象的方法,用+。+用來修飾類的方法,使用+修飾的類方法,是整個類的方法,不屬於哪個類對象,這與C++中的static在類中使用的概念同樣,
%@
在NSLog中,使用%@表示要調用對象的description方法。
概念
類
是一種結構,它表示對象的類型,就像int與 char 同樣,也能夠聲明類的變量(對像)
實例化
爲類的對象分配內存和初始化,達到能夠使用該 類對象的目的。
對象(實例)
類的實例化後的產物
消息
在 Object-C中,類的對象執行的操做,是經過給該類或者該類對象發送消息實現,如:[object func];就是給object對象發送 func消息,相似C++中的方法調用。給object對象發送func消息後,object對象查詢所屬類的func方法執行。
方法調度
當向一個對象發送消息時(調用方法),這個方法是怎麼被調用的呢?這就依賴於方法高度程序,方法調度程序查找的方法以下:
在本類的方法中,找被調用的方法,若是找到了,就調用,若是找不到被沿着繼承路徑去查找,從哪一個類找到,就調用哪一個類的方法,若是到最根上的類仍是沒有找到,那編譯就會出錯。
繼承與複合
在Objective-C中支持繼承,但只是支持單一繼承(有且只有一個父類有),若是想使用多繼承的特性,能夠使用分類和協議技術。
繼承是is-a,複合是has-a。複合是經過包含指向對象的指針實現的,嚴格意義上講,複合是針對於對象間來講,對於基本數據類型來講,它們被認爲是對象的一部分。
裝箱與拆箱
因爲NSArray,NSDirectory等類不能直接存儲基本數據類型,因此要想在NSArray\NSDirectory中使用基本數據類型,就得使用裝箱與拆箱。
在Objective-C中,能夠使用NSNumber和NSValue來實現對數據類型的包裝,NSNumber能夠實現對基本數據類型的包裝,NSValue能夠實現對任意類型數據的包裝。
將基本類型封裝成對象叫裝箱,從封裝的對象中提取基本類型叫拆箱(取消裝箱),其它語言如Java原生支持裝箱與拆箱,Ojbective-C不支持自動裝箱與拆箱,若是須要得須要本身來實現裝箱與拆箱。
存取方法
在 使用類對象的實例變量(成員數據)時,不要直接使用對象中的實例,要使用存以方法來獲取或者修改實例,既setter和getter,在 Cocoa中, 存取方法有命名習慣,咱們得符合這種習慣,以便於與其它團隊成員合做。setter方法是修改或者設置實例值,命名習慣爲set+實例名,例有一個類有 path實例變量,那setter命名爲setPath,getter命名爲Path,爲何不是getPath,由於get在Cocoa中有特殊的含 義,這個含義就是帶有get的方法就意味着這個方法經過形參指針(傳入函數的參數指針)來返回值。咱們要遵照這個命名習慣或者說規則。
在Objective-C 2.0中加入了@property和@synthesize來代替setter和getter,這兩個關鍵字爲編譯器指令。還有點表達式,存取類成員的值時,能夠使用點表達式。
Object.attribute,當點表達式在=號左邊時,調用的是setter方法,在=號右邊時,調用的是getter方法。
@property 語法爲:@property (參數) 類型 變量名.
在這裏主要說明一下參數.
參數分爲三種:
第一種:讀寫屬性包括(readonly/readwrite/)
第 二種:setter屬性(assign,copy,retain),assign是簡單的賦值,copy是釋放舊成員變量,並新分配內存地址給成 員 變量,將傳入參數內容複製一份,給成員變量。retain是將傳入 參數引用計數加1,而後將原有的成員變量釋放,在將成員變量指向該傳入參數。
第三種:與多線程有關(atomic,nonatomic).當使用多線程時,使用atomic,在不使用多線程時使用nonatomic
對象建立與初始化
在Objective-C中建立對象有兩種方法,一種是[類 new];另外一種是[[類 alloc] init],這兩種方法是等價的,但按慣例來說,使用[[類 alloc] init];
alloc操做是爲對象分配內存空間,並將對象的數據成員都初始,int 爲0,BOOL 爲NO, float 爲0.0等。
初始化,默認的初始化函數爲init,init返回值爲id,爲何回返回id呢,由於要實現鏈式表達式,在Objective-C中叫嵌套調用。
爲何要嵌套調用??由於初始化方法init返回值可能與alloc返回的對象不是同一個?爲何會發生這種狀況?基於類簇的初始化,由於init能夠接受參數,在init內部有可能根據不一樣的參數來返回不一樣種類型的對象,因此最會發生上面說的狀況。
在初始化時,建議使用if (self = [super init])
便利初始化
當一個類須要根據不一樣的狀況來初始化數據成員時,就須要便利初始化函數,與init初始化不一樣的是,便利初始化函數有參數,參數個數能夠有1到N個,N是類數據成員個數。
指定初始化函數:什麼是指定初始化函數?在類中,某個初始化函數會被指定爲指定的初始化函數,肯定指定初始化函數的規則是初始化函數中,參數最多的爲指定初始化函數,
其它未被指定爲指定初始化函數的初始化函數要調用指定初始化函數來實現。對於該類的子類也是同樣,只要重寫或者直接使用父類的指定初始化函數。上述文字有些繞,來個例子吧
@interface A{
int x;
int y;
}
-(id) init;
-(id) initWithX:(int) xValue;
-(id) initWithY:(int) yValue;
-(id) initWithXY:(int) xValue
yVal:(int) yValue;
@end
這裏initWithXY被肯定爲指定初始化函數。
-(id) initWithXY:(int) xValue
yVal:(int) yValue{
if (self = [super init]){
x = xValue;
y = yValue;
}
return self;
}
-(id) init{
if (self = self initWithXY:10
yVal:20){
}
return self;
}
.......
@interface B: A{
int z;
}
-(jd) initWithXY......;
@end
@implementation B
-(id) initWithXY:(int) xValue
yVal:(int) yValue{
if (self = [super initWithXY:10
yVal=20]){
z= 40;
}
return self;
}
@end
自動釋放池
內存管理是軟件代碼中的重中之重,內存管理的好壞,直接影響着軟件的穩定性。在Cocoa中,有自動釋放池,這相似於C++中的智能指針。
NSObject有一個方法是autorelease,當一個對象調用這個方法時,就會將這個對象放入到自動釋放池中。
drain,該方法是清空自動釋放池,不是銷燬它。drain方法只適用於Mac OS X 10.4以上的版本,在咱們寫的代碼中要使用release,release適用於全部版本。
自 動釋放池是以棧的方式實現,當建立一個自動釋放池A時,A被壓入棧頂,這時將接入autorelease消息的對象放入A自動釋放池,這時建立一 個新的 B自動釋放池,B被壓入棧頂,建立完成後刪除B,這個接收autorelease消息的對象依然存在,由於A自動釋放池依然存在。
引用計數
每一個對象都有一個與之相應的整數,稱它爲引用計數,當該引用計數爲0時,Objective-C自動向該對象發送dealloc,以銷燬該對向,與該引用計數相關的方法(消息)有下面幾個
1 增長引用計數:經過alloc,new,copy建立一個對象時,該對象的引用計數加1(其實就是1,由於以前爲0)
2 增長引用計數: retain
3 減小引用計數: release
局部分配內存(臨時對象):
1 若是使用alloc,new,copy建立對象,則須要主動調用對象的release方法
2 若是使用非alloc,new,copy建立對象,咱們認爲該對象引用計數爲1,並已經加入了自動釋放池,咱們不須要主動的調用對象的release方法。
擁有對象(在類中以成員的方法存在):
1 若是使用alloc,new,copy建立對象,則須要在dealloc方法中,釋放該對象
2 若是使用非alloc,new,copy建立對象,則在擁有該對象時,保留該對象(執行retain方法),在dealloc方法中,釋放該對象。
dealloc
當對象的引用計數爲0時,Objective-C會自動發送對象的dealloc消息(自動調用對象的dealloc方法,相似於C++的析構函數),因此咱們能夠本身重寫dealloc方法,來實現類裏的對其它使用資源的釋放工做。
注意:不要直接在代碼中顯示調用dealloc方法。
垃圾回收
在Objective-C 2.0中引入了垃圾回收機制(自動管理內存),在工程設置裏設置Objective-C Garbage Collection爲Required[-fobjc-gc-only]就能夠使用垃圾回收機制。
啓用垃圾回收機制後,一般的內存管理命令都變成了空操做指令,不執行任何操做。
Objective-C的垃圾回收機制是一種繼承性的垃圾回收器,垃圾回收器按期檢查變量和對象以及他們之間的指針,當發現沒有任何變量指向對象時,就將該對象視爲被丟棄的垃圾。因此在不在使用一個對象時,將指針他的指針設置爲nil,這時垃圾回收器就會清理該對象。
注意:若是開發iphone軟件,則不能使用垃圾回收。在編寫iPhone軟件時,Apple公司建議不要在本身的代碼中使用autorelease方法,而且不要使用建立自動釋放對象的函數。
類別
什麼是類別?類別是一種爲現有類添加新方法的方式。
爲何使用類別或者說使用類別的目的是什麼?有如下三點:
第一,能夠將類的實現分散到多個不一樣的文件或多個不一樣的框架中。
若是一個類須要實現不少個方法,咱們能夠將方法分類,把分好的類造成類別,能夠有效的管理和駕馭代碼。
第二,建立對私有方法的前向引用。
第三,向對象添加非正式協議。
委託
委託的意思就是你本身想作某事,你本身不作,你委託給別人作。
在Ojbective-C中,實現委託是經過類別(或非正式協議)或者協議來實現。
舉 個例子:Apple要生產iPhone,Apple本身不生產(種種緣由,其中之一就是在中國生產成本低,他們賺的銀子多),Apple委託富士 康來生 產,原本富士康原來不生產iPhone,如今要生產了,因此他得本身加一個生產iPhone的生產線(類別,增長生產iPhone方法),這就是經過類別 來實現委託。下面用代碼來講明這個例子。
.....
Apple *apple = [[Apple alloc ] init];
Foxconn *fox = [[Foxconn alloc] init];
[apple setDelegate:fox];
[apple produceIPhone];
........
@implementation Apple
-(...) setDelegate:(id) x{
delegate = x; //! 將委託的生產對象指定爲x
}
-(...) produceIPhone{
[delegate produceIPhone]; //! 委託對象生產iPhone
}
@interface Foxconn : NSObject
...
@end
@interface NSObject(ProduceIPhone) //! Foxconn以前就能夠生產其它產品,有過聲明和定義
-(...) produceIPhone //! 增長生產iPhone能力
@end
@implementation NSObject(ProduceIPhone)
//! 生產iPhone
-(...) produceIPhone{
......
}
@end
非正式協議
建立一個NSObject的類別, 稱爲建立一個非正式協議。爲何叫非正式協議呢?
也就是說能夠實現,也能夠不實現被委託的任務。
拿上面的例子來講,Apple要求Foxconn除了能生產iPhone外,還有一個要求是在必定時間內完成.因爲雙方沒有籤合同,因此時間要求和生產要求規格都是非正式協議
選擇器
選 擇器就是一個方法的名稱。選擇器是在Objective-C運行時使用的編碼方式,以實現快速查找。能夠使用@selector預編譯指令,獲取 選擇器 @selector(方法名)。NSObject提供了一個方法respondsToSelector:的方法,來訪問對象是否有該方法(響應該消息)。
拿 上面的Apple請Foxconn生產iPhone爲例,Apple怎麼知道Foxconn有沒有生產iPhone的能力呢?Apple就經過 respondsToSelector方法詢問Foxconn,是否能夠生產iPhone(是否能夠響應produceIPhone),詢問結果是能夠, 那Apple就委託Foxconn生產,Foxconn就生產出來了人們比較喜歡的iPhone產品。
正式協議
與非正式協議比較而言,在Ojbective-C中,正式協議規定的全部方法必須實現。在Ojbective-C2.0中,Apple又增長了兩個關鍵字,協議中的方法也能夠不徹底實現,是哪一個關鍵字見關鍵字部份的@optional,@required。
正式協議聲明以下:
@protocol XXX
-(...) func1;
-(...) func2;
@end
使用協議:
@interface Object : NSObject //! Object從NSObject派生,並遵循XXX協議,要實現func1,func2函數。
...
@end
習慣用法
分配內存和初始化
self = [super init];
對象間交互
在Objective-C中,全部對象間的交互都是經過指針實現。
快速枚舉
for (Type *p in array)
注意:
Objective-C不支持多繼承
objective-c只不過是擁有一些附加特性的C語言。本質上就是C語言
1.C語言使用#include通知編譯器應在頭文件中查詢定義。objective-c也能夠使用#include來實現這個目的,但你永遠不可能這麼作,你會用#import,它是GCC編譯器提供的,#import能夠保證頭文件只被包含一次。
xcode會使用預編譯頭文件(一種通過壓縮的,摘要形式的頭文件),在經過#import導入這種文件時,加載速度會很是快。
2.什麼是框架
框架是一種彙集在一個單元的部件集合,包含頭文件,庫,圖像,聲音文件等。蘋果公 司將cocoa,Carbon,QuickTime和OpenGL 等技術 做爲框架集提供。cocoa的組成部分有Foundation和Application Kit框架。還有一個支持框架的套件,包含 Core Animation和Core Image,這爲Cocoa增添了多種精彩的功能。
每一個框架都是一個重要的技術集合,一般包含數十個甚至上百個頭文件。每一個框架都有一個主頭文件,它包含了全部框架的各個頭文件。經過使用#import導入主頭文件,能夠使用全部框架的特性。
3.Foundation框架處理的是用戶界面之下的層(layer)中得特性,例如數據結構和通訊機制。
4.NS前綴
NS這個前綴告訴你函數來自cocoa而不是其餘工具包。
兩個不一樣事物使用相同標示符時會致使名稱衝突,而前綴能夠預防這個大問題。
5.BOOL類型
objective-c中得BOOL其實是一種對帶符號的字符類型(signed char)的定義。它使用8位存儲空間,YES爲1,NO爲0.
6.間接
不在代碼中直接使用某個值,而是使用指向該值的指針。另外一個意思是,讓別的類來完成本類的工做。
例子:
1.循環次數的變量。變量與間接
2.使用從文件讀取。文件與間接
在OOP(面向對象編程)中,間接十分重要。OOP使用間接來獲取數據,OOP真正的革命性就是它在調用代碼中使用間接。好比在調用函數時,不是直接調用,而是間接調用。
7.過程式程序與OOP的區別
過程式程序創建在函數之上,數據爲函數服務。面向對象編程從相反的角度來看待問題。它以程序的數據爲中心,函數爲數據服務。在OOP中,不在重點關注程序中得函數,而是專一與數據。
8.id
id是一種泛型,用於表示任何種類的對象。
9.OOP中得一些術語
類:類是一種結構,它表示對象的類型。對象引用類來獲取和自己有關的各類信息,特別是運行什麼代碼來處理每種操做。
對象:對象是一種結構,它包含值和指向其類的隱藏指針。
實例:實例是「對象」的另外一種稱呼。
消息:消息是對象能夠執行的操做,用於通知對象去作什麼。
方法:方法是爲響應消息而運行的代碼。根據對象的類,消息能夠調用不一樣的方法。
方法調度程序:是objective-c使用的一種機制,用於推測執行什麼方法以響應某個特定的消息。
接口:接口是對象的類應該提供的特性的描述。接口不提供實現細節。
實現:實現是使接口正常工做的代碼。
10.中綴符
objective- c有一種名爲中綴符的語法技術。方法的名稱及其參數都是合在一塊兒的。例如: [trxtThing setStringValue:@"Hello there" color:kBlueColor]; 中 setStringValue: 和 color:其實是參數的名稱(其實是方法名稱的一部分)。使代碼可讀性更強,更容易理解參數的用途。
11.先行短線
-(void)draw;
前面的短線代表這是objective-c方法的生命。這是一種區分函數原型與方法聲明的方式,函數原型中沒有先行短線。-表明是實例方法。+表明是類方法。
12.@interface
建立某個特定類的對象以前,objective-c編譯器須要一些有關該類的信息。他必須知道對象的數據成員和它提供的特性能夠使用@interface指令把這種信息傳遞給編譯器。用於定義類的公共接口。
13.@implementation
是一個編譯器指令,代表你將爲某個類提供代碼。類名出如今@implementation以後。該行的結尾處沒有分號。由於在objective-c編譯器指令後沒必要使用分號。
@interface和@implementation間的參數名不一樣是正確的。
在@interface中沒有聲明卻在@implementation中實現的方法是私有方法。
14.實例化
建立對象的過程叫作實例化。實例化對象時,須要分配內存,而後這些內存被初始化並保存一些有用的默認值,這些值不一樣於你在得到新分配內存時獲得的隨機值。內存分配和初始化完成後,就建立了一個新的對象實例。
15.繼承
建立一個新類時,一般須要定義新類以區別於其餘類以及現有類。使用繼承能夠定義一個具備父類全部功能的新類,它繼承了父類的這些功能。
objective-c沒有多繼承。
建立一個新類時,其對象首先從自身的超類中繼承實例變量,而後添加他們本身的實例變量。
超類
父類
子類
孩子類
重寫
方法調度:objective-c的方法調度程序將子當前類中搜索響應的方法。若是調度程序沒法在接受消息的對象類中找到響應的方法,它就會在該類的超類中進行查找。順着繼承鏈找到下一個超類進行查找,直到NSObject類中也沒有該方法,則會出現運行時錯誤。
16.複合
對象引用其餘對象時,能夠利用其餘對象提供的特性,這就是複合。
17.UML
UML是一種用圖表表示類,類的內容以及他們之間關係的常見方法。
18.多態
使用更具體種類的對象(子類對象)代替通常類型(父類),這種能力稱爲多態性。
19.self
是一個指向接收消息的對象的指針。指向第一個實例變量isa。由於objective-c編譯器已經看到了全部這些類的@interface聲明,所以,它能直到對象中實力變量的佈局,經過這些重要的信息,編譯器能夠產生代碼並查找任何須要的實例變量。
基地址加偏移:編譯器使用「基地址加偏移」機制實現奇妙的功能。給定的對象基地址,是指第一個實例變量的首個字節在內存中得位置,經過在該地址加上偏移地址,編譯器就能夠查到其餘實例變量的位置。
20.間接尋址方式,直接尋址方式
21.super
objective-c提供某種方式來重寫方法,而且仍然調用超類的實現方式。當須要超類實現自身的功能,同時在前面或者後面執行某些額外的工做時,這種機制很是有用。爲了調用繼承方法的實現,須要使用super做爲方法調用的目標。
22.cocoa
cocoa其實是由2個不一樣的框架組成的:Foundation Kit和 Application Kit。Application Kit包含了全部的用戶接口對象和高級類。
Foundation Kit
23.NSAutoreleasePool
mian()函數建立了(經過alloc)並初始化(經過init)了一個NSAutoreleasePool實例。在mian()函數結尾,這個池被排空。這就是Cocoa內存管理的預覽。
24.NSRange
typedef struct _NSRange {
unsigned int location;
unsigned int length;
}NSRange;
這個結構體用來表示相關事務的範圍,一般是字符串裏的字符範圍或者數組裏的元素範圍。
25.三種賦值方式
1.NSRange range;
range.location = 17;
range.length = 4;
2.C語言的聚合結構賦值機制
NSRange range = {17, 4};
3.Cocoa提供的一個快捷函數NSMakeRange()
NSRange range = NSMakeRange(17, 4);
使用NSMakeRange()的好處是你能夠在任何可以使用函數的地方使用它,例如在方法調用中將其當成參數傳遞。
26.幾何數據類型
1.NSPoint 表明笛卡兒平面中得一個點(x, y).
typedef struct _NSPoint {
float x;
float y;
}NSPoint;
2.NSSize 用來存儲長度和寬度
typedef struct NSSize {
float width;
float height;
}NSSize;
3.NSRect 矩形數據類型,它是由點和大小複合而成
typedef struct _NSRect {
NSPoint origin;
NSSize size;
}NSRect;
27.字符串NSString
stringWithFormat:就是一個工廠方法,它根據你提供的參數建立新對象。
length:長度
isEqualToString:比較字符串內容是否相同
compart:將接受對象和傳遞來的字符串逐個字符的進行比較。返回一個enum數據
NSCaseInsensitiveSearch:不區分大小寫字符。
NSLiteralSearch:進行徹底比較,區分大小寫
NSNumericSearch:比較字符串的字符個數,而不是字符值。
-(NSRange)rangeOfString:(NSString *)aString;
返回的range.start爲開始位置,range.length爲長度。
28.NSMutableString可變字符串。
stringWithCapacity:建立一個新的NSMutableString
字符串的大小並不只限於所提供的容量,這個容量僅是個最優值。若是要建立一個40mb的字符串。
NSMutableString *str = [NSMutableString stringWithCapacity:42];
appendString接受參數aString,而後將其複製到接收對象的末尾。
appendFormat與stringWithFormat:相似,但它將格式化的字符串附加在接收字符串的末尾,而不是建立新的字符串對象。
29.集合家族
1.NSArray:是一個Cocoa類,用來存儲對象的有序列表。
兩個限制:1.只能存儲objective-c的對象,不能存儲C語言中得基本數據類型。
2.也不能存儲nil。
30.枚舉器,快速枚舉
31.NSDictionary字典
關鍵字及其定義的集合。
32.NSNumber包裝(以對象形式實現)基本數據類型
裝箱:將一個基本類型的數據包裝成對象。
取消裝箱:從對象中提取基本類型的數據。
objective-c不支持自動裝箱。
33.NSValue是NSNumber的父類。
+(NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type;
傳 遞的參數是你想要包裝的數值的地址(如一個NSSize或你本身的struct)。一般,獲得的是你想要存儲的變量的地址(在C語言中使用操做 符&)。你也能夠提供一個用來描述這個數據類型的字符串,一般用來講明struct中實體的類型和大小。你不用本身寫代碼來生成這個字符 串,@encode編譯器指令能夠接受數據類型的名稱併爲你生成合適的字符串。
NSRect rect = NSMakeRect(1, 2, 30, 40);
NSValue *value;
value = [NSValue valueWithBytes:&rect objCType:@encode(NSRect)];
[array addObject:value];
34.NSNull只有一個方法[NSNull null];
[NSNull null]老是返回同樣的數值,因此你能夠使用運算符==將該值與其餘值進行比較。
35.單實例架構:只須要一個實例。
查找文件:
例如:NSFileManager *manager;
manager = [NSFileManager defaultManager];
defaultManager能夠爲咱們建立一個屬於咱們本身的NSFileManger對象。
NSString *home = [@"~" stringByExpandingTildeInPath];將~替換成當前用戶的主目錄。
NSDirectoryEnumerator *direnum = [manager enumeratorAtPath:home]; 返回一個 NSDictionaryEnumerator,它是NSEnumerator的子類。每次在這個枚舉器對象中調用nextObject時,都會返回該目 錄中得一個文件的另外一個路徑。
36.內存管理
1)對象生命週期
對象的生命週期包括誕生(alloc或者new方法實現),生存(接受消息和執行操做),交友(藉助方法的組合和參數)以及當他們的生命結束時最終死去(被釋放)。當對象的生命週期結束時,他們的原材料(內存)將被回收以供新的對象使用。
2)引用計數
cocoa 採用了一種稱爲引用計數的技術,有時候也叫保留計數。每一個對象有一個與之相關聯的整數,稱做它的引用計數器或保留計數器。當某段代碼須要 訪問一 個對象時,該代碼將該對象的保留計數器值+1,表示「我要訪問該對象」。當這段代碼結束對象訪問時,將對象的保留計數器值-1,表示它再也不訪問該對象,當 保留計數器值爲0時,表示再也不有代碼訪問該對象了,所以該對象被銷燬,其佔用的內存被系統回收以便重用。
alloc,new,copy 1
retain +1
release -1
3)對象全部權
若是一個對象具備指向其餘對象的實力變量,則稱該對象擁有這些對象。
在類A中 B對象擁有其指向的C對象,則B對象擁有C對象。
若是一個函數建立了一個對象,則稱該函數擁有它建立的這個對象。
main()函數建立了對象a 稱main()函數擁有a對象
當多個實體擁有某個特定的對象時,對象的全部權關係就更加複雜了,這也是保留計數器值可能大於1的緣由。
例子:
main() {
Engine *engine = [Engine new];
[car setEngine:engine];
}
現 在哪一個實體擁有engine對象?是main函數仍是car類?哪一個實體負責確保當engine對象再也不被使用時可以收到release消息?因 爲 car類正在使用engine對象,因此不多是main函數。由於main函數隨後還可能會使用engine對象,因此也不多是car類。
解 決方法是讓car類保留engine對象,將engine對象的保留計數器值增長到2。這是由於car類和main函數這2個實體都正在使用 engine對象。car類應該在setEngine:方法中保留engine對象,而main函數應該釋放engine對象。而後,當car類完成其任 務時再釋放engine對象(在其dealloc方法中),最後engine對象佔用的資源被回收。
若是您使用名字以「alloc」或 「new」開頭或名字中包含「copy」的方法(例如alloc,newObject或mutableCopy) 建立了 一個對象,則您會得到該對象的全部權;或者若是您向一個對象發送了一條retain消息,則您也會得到該對象的全部權。
4)訪問方法中得保留和釋放
5)自動釋放池NSAutoreleasePool
是一個存放實體的池(集合)。你能夠用NSMutableArray來編寫本身的自動釋放池,以容納對象並在dealloc方法中向池中得全部對象發送release消息。
autorelease
當給一個對象發送autorelease消息時,其實是將該對象添加到NSAutoreleasePool中。當自動釋放池被銷燬時,會向該池中得全部對象發送release消息。
6)自動釋放池的銷燬時間
在咱們一直使用的Foudation庫工具中,建立和銷燬自動釋放池的方法很是明確:
NSAutoreleasePool *pool;
pool = [[NSAutoreleasePool alloc] init];
...
[pool release];
創 建一個自動釋放池時,該池自動成爲活動的池。釋放該池時,其保留計數器值歸0,而後該池被銷燬。在銷燬的過程當中,該池釋放其包含的全部對象。當使 用 Application Kit時,cocoa按期自動爲你建立和銷燬自動釋放池。一般是在程序處理完當前事件之後執行這些操做。你能夠使用任意多得自動 釋放對象,當再也不使用它們時,自動釋放池將自動爲你清理這些對象。
你可能已經在xcode自動生成代碼中碰見過另外一種銷燬自動釋放池中對象的方式:-drain方法。該方法只是清空自動釋放池而不是銷燬它。而且只適用於mac os x10.4以上的版本。
7)自動釋放池的工做過程
我 們在任什麼時候候向一個對象發送autorelease消息,該對象都會唄添加到這個自動釋放池中。被加入到自動釋放池的對象的引用計數器值不會變 化。當自 動釋放池被銷燬時(向自動釋放池發送release消息,自動釋放池的引用計數器值變爲0,調用自身的dealloc函數),會調用自身的dealloc 函數,會向池中得對象發送release消息。
37.cocoa內存管理規則
1)當你使用new,alloc或copy方法建立一個對象時,該對象的保留計數器值爲1。當再也不使用該對象時,你要負責向該對象發送一條release或autorelease消息。這樣,該對象將在其使用壽命結束時被銷燬。
2)當你經過任何其餘方法得到一個對象時,則假設該對象的保留計數器值爲1,並且已經被設置爲自動釋放,你不須要執行任何操做來確保該對象被清理。若是你打算在一段時間內擁有該對象,則須要保留它並確保在操做完成時釋放它。
3)若是你保留了某個對象,你須要(最終)釋放或自動釋放該對象。必須保持retain方法和release方法的使用次數相同。
38.清理自動釋放池
因爲自動釋放池的銷燬時間是徹底確立的,因此它在循環執行過程當中不會被銷燬。在迭代中或者循環中,須要創建本身的自動釋放池。
39.垃圾回收gc
自 動內存管理機制。objective-c的垃圾回收器是一種繼承性的垃圾回收器。與那些已經存在了一段時間的對象相比,新建立的對象更可能被當成 垃圾。 垃圾回收器按期檢查變量和對象以及他們之間的指針,當發現沒有任何變量指向某個對象時,就將該對象視爲應該被丟棄的垃圾。若是你再一個實例變量中指向某個 對象,必定要在某個時候使該實例變量賦值爲nil,以取消對該對象的引用並使垃圾回收器知道該對象能夠被清理了。
與自動釋放池同樣,垃圾回收器也是在時間循環結束時才觸發。
ARC是什麼?
ARC是iOS 5推出的新功能,全稱叫 ARC(Automatic Reference Counting)。簡單地說,就是代碼中自動加入了retain/release,原先須要手動添加的用來處理內存管理的引用計數的代碼能夠自動地由編譯器完成了。
該 機能在 iOS 5/ Mac OS X 10.7 開始導入,利用 Xcode4.2 能夠使用該機能。簡單地理解ARC,就是經過指定的語 法,讓編 譯器(LLVM 3.0)在編譯代碼時,自動生成實例的引用計數管理部分代碼。有一點,ARC並非GC,它只是一種代碼靜態分析 (Static Analyzer)工具。
40.分配
是一個新對象誕生的過程。是從操做系統得到一塊內存並將其指定爲存放對象的實例變量的位置。
40.初始化
與分配對應的操做是初始化。初始化從操做系統取得一塊內存。準備用於存儲對象。
嵌套調用技術很是重要,由於初始化方法返回的對象可能與分配的對象不一樣。
1)初始化時作什麼?
給實例變量賦值並建立你得對象完成任務所須要的其餘對象。
2)便利初始化函數
許多類包含便利初始化函數。用來完成某些額外的工做的初始化方法,能夠減小你本身完成這些工做的麻煩。
例如:NSString類中-(id)initWithFormat:(NSString *)format,...;
3)指定初始化函數
類中的某個初始化方法被指派爲指定初始化函數。該類全部初始化方法使用指定初始化函數執行初始化操做。子類使用其超類的指定初始化函數實現超類的初始化。
例如:其餘初始化函數經過指定初始化函數實現。
41.初始化函數規則
不須要爲你本身的類建立初始化函數方法。若是不須要設置任何狀態,或者只須要alloc方法將內存清零的默認行爲,則不須要擔憂init。
若是構造了一個初始化函數,則必定要在你本身的指定初始化函數中調用超類的指定初始化函數。必定要將超類的初始化函數的值賦給self對象,並返回你本身的初始化方法的值。由於超類可能決定返回一個徹底不一樣的對象。
若是初始化函數不止一個,則要選擇一個座位指定初始化函數。被選定的方法應該調用超類指定初始化函數。要按照指定初始化函數的形式實現全部其餘初始化函數,就像咱們在前面的實現同樣。
42.特性@property
objective-c2.0的特性只適用於mac os x 10.5或更高版本。特性主要應用於cocoa的新組件(尤爲是華麗奪目的core Animation效果)。
1)簡化接口
@property預編譯指令的做用是自動生命屬性的setter和getter方法。
2)@synthesize也是一種新的編譯器功能,表示「建立該屬性的訪問器」。
3)點表達式
若是點表達式出如今=左邊,該屬性名稱的setter方法(set方法)將被調用。若是點表達式出如今對象變量右邊,則該屬性名稱的getter方法(get方法)將被調用。
4)特性擴展
@property()括號裏面的東西,是對應在set方法中要添加的語句。好比我在括號裏寫retain,就至關於在它的set方法裏添加了一句 [xx retain]。
@property屬性
屬性分爲3類:
1.讀寫屬性(Writability)包含:readwrite / readonly
2.setter語義(Setter Semantics)包含:assign / retain / copy
3.原子性(Atomicity)包含:nonatomic
下面具體說明各個屬性的含義
readwrite / readonly:
決定是否生成set訪問器,readwrite是默認屬性,生成getter和setter方法;readonly只生成getter方法,不生成setter方法。
readonly關鍵字表明setter不會被生成, 因此它不能夠和 copy/retain/assign組合使用。
assign / retain / copy:
這些屬性用於指定set訪問器的語義,也就是說,這些屬性決定了以何種方式對數據成員賦予新值。
assign:
直接賦值,索引計數不改變,適用於簡單數據類型,例如:NSIngeter、CGFloat、int、char等。
retain:
指針的拷貝,使用的是原來的內存空間。
對象的索引計數加1。
此屬性只能用於Objective-C對象類型,而不能用於Core Foundation對象。(緣由很明顯,retain會增長對象的引用計數,而基本數據類型或者Core Foundation對象都沒有引用計數)。
copy:
對象的拷貝,新申請一塊內存空間,並把原始內容複製到那片空間。
新對象的索引計數爲1。
此屬性只對那些實行了NSCopying協議的對象類型有效。
不少Objective-C中的object最好使用用retain,一些特別的object(例如:string)使用copy。
nonatomic:
非原子性訪問,不加同步,多線程併發訪問會提升性能。若是不加此屬性,則默認是兩個訪問方法都爲原子型事務訪問。默認值是atomic,爲原子操做。
(atomic是Objc使用的一種線程保護技術,基本上來說,是防止在寫未完成的時候被另一個線程讀取,形成數據錯誤。而這種機制是耗費系統資源的, 因此在iPhone這種小型設備上,若是沒有使用多線程間的通信編程,那麼nonatomic是一個很是好的選擇。)
5)保留週期retain cycle
引用計數器在該週期中歸零。
6)什麼是屬性訪問器
屬性訪問器(Property Accessor),包括 get 訪問器和 set 訪問器分別用於字段的讀寫操做
其設計目的主要是爲了實現面向對象(OO)中的封裝思想。根據該思想,字段最好設爲private,一個精巧的類最好不要直接把字段設爲公有提供給客戶調用端直接訪問
另外要注意屬性自己並不必定和字段相聯繫
7)self.a與a的區別
self.a使編譯器知道咱們指望使用訪問器訪問a。若是隻使用裸名a,編譯器將假設咱們直接修改了實例變量。
8)self.a = nil
這 行代碼表示使用nil參數調用setName:方法。生成的訪問器方法將自動釋放之前的name對象,並使用nil替代a。該方法完成了釋放 name對 象所佔用內存的操做。固然,也能夠只釋放name對象以清理其佔用的內存。若是你再dealloc方法之外的地方清除特性,那麼使用"將nil賦值給對 象"的方法能夠將特性設置爲nil,同時能夠使咱們避免對已釋放內存的懸空引用問題。
9)特性不是萬能的
有些方法不適合特性所能涵蓋的方法的至關狹小的範圍。特性不支持那些須要接受額外參數的方法。
43.類別@category
1)聲明類別
@interface NSString (NumberConvenience)
-(NSNumber *)lengthAsNumber;
@end
該 聲明具備2個特色。首先,現有類位於@interface關鍵字以後,其後是位於圓括號中的一個新名稱。該聲明表示,類別的名稱是 NumberConvenience,並且該類別將向NSString類中添加方法。只要保證類別名稱的惟一性,你能夠向一個類中添加任意多得類別。
其次,你能夠指定但願向其添加類別的類以及類別的名稱,並且你還能夠列出添加的方法,最後以@end結束。因爲不能添加新實現變量,所以與類聲明不一樣的是,類別的聲明中沒有實例變量部分。
2)實現類別
3)類別的侷限性
第一,沒法向類中添加新的實例變量。類別沒有位置容納實例變量。
第二,名稱衝突,即類別中得方法與現有的方法重名。當發生名稱衝突時,類別具備更高的優先級。你得類別方法將徹底取代初始方法,從而沒法再使用初始方法。有些編程人員在本身的類別方法中增長一個前綴,以確保不發生名稱衝突。
有一些技術能夠克服類別沒法增長新實例變量的侷限。例如,能夠使用全局字典存儲對象與你想要關聯的額外變量之間的映射。但此時你可能須要認真考慮一下,類別是不是完成當前任務的最佳選擇。
4)類別的做用
cocoa中得類別主要用於3個目的:第一,將類的實現分散到不一樣文件或者不一樣框架中。第二,建立對私有方法的前向引用。第三,向對象添加非正式協議。
44.run循環是一種cocoa構造,它一直處於阻塞狀態(即不執行任何處理),知道某些事件發生爲止。
45.響應選擇器
一個類別如何知道其委託對象是否可以處理那些發送給它的消息?
類別首先檢查對象,詢問其可否響應該選擇器。若是該對象可以響應該選擇器,
1)選擇器@selector()
選擇器只是一個方法名稱,但它以objective-c運行時使用的特殊方式編碼,以快速執行查詢。你能夠使用@selector()預編譯指令選擇器,其中方法名位於圓括號中。
46.委託 非正式協議
47.正式協議
與非正式協議同樣,正式協議是一個命名的方法列表。但與非正式協議不一樣的是,正式協議要求顯式的採用協議。採用協議的辦法是在類的@interface聲明中列出協議名稱。採用協議意味着你承諾實現該協議的全部方法。
1)聲明協議
@protocol NSCopying
-(id)copyWithZone:(NSZone *)zone;
@end
2)採用協議
@interface Car: NSObject
{
}
@end
3)協議和數據類型
若是一個用尖括號括起來的協議名稱跟隨在id以後,則編譯器將知道你指望任意類型的對象,只要其遵照該協議。
4)objective-c2.0的新特性@optional @required
@optional可選擇實現的方法
@required必須實現的方法
所以cocoa中得非正式協議正被帶有@optional的正式協議所取代。
48.Application Kit
1)IBOutlet與IBAction
他 們實際上只是APPKit提供的#defines。IBOutlet的定義沒有任何做用,所以將不會對它進行編譯。IBAction定義爲 void,這 意味着在AppController中聲明的方法的返回類型將使void。IBOutlet和IBAction不執行任何操做,他們並非用於編譯的,實 際上他們是爲Interface Builder以及閱讀代碼的人提供的標記。經過查找IBOutlet和 IBAction,Interface Builder知道AppController對象具備兩個可以鏈接的實例變量。
2)IBOutlet是如何工做的
當 加載nib文件時(MainMenu.nib會在應用程序啓動時自動加載,能夠建立你本身的nib文件並自行加載),存儲在nib文件中得任何對 象都會 被從新建立。這意味着會再後臺執行alloc和init方法。因此,當應用程序啓動時,會分配並初始化一個AppController實例。在執行 init方法期間,全部IBOutlet實例變量都爲nil。只有建立了nib文件中得全部對象(這包括窗口和文本域和按鈕),全部鏈接纔算完成。
一 旦創建了全部鏈接(也就是將NSTextField對象的地址添加到AppController的實例變量中),會向建立的每一個對象發送消息 awakeFromNib。一個很是常見的錯誤是試圖在init方法中使用IBOutlet執行一些操做。因爲全部實例變量都爲nil,發送給他們的全部 消息不執行任何操做,因此在init中得任未嘗試都會發生無提示失敗。(這是Cocoa致使效率低和佔用大量調試時間的一個方面)。若是你想知道爲何這 些操做不起做用,能夠使用NSLog輸出實例變量的值,並查看他們是否都爲nil。對於建立的對象和發送的awakeFromNib消息,都不存在預約義 順序。
文件加載與保存
49.屬性列表
1)自動釋放對象
NSDate
NSData NSData對象是不可改變的。他們被建立後就不能改變。能夠使用他們,但不能改變其中的內容。
2)編碼對象 編碼和解碼
cocoa具有一種機制來將對象自身轉換爲某種格式並保存到磁盤中。對象能夠將他們的實例變量和其餘數據塊編碼爲數據塊,而後保存到磁盤中。之後將這些數據塊讀回到內存中,而且還能基於保存的數據建立新對象。這個過程稱爲編碼和解碼。或稱爲序列化和反序列化。
50.鍵/值編碼 KVC
是一種間接改變對象狀態的方式,其實現方法是使用字符串描述要更改的對象狀態部分。
1)valueForKey與setValue:forKey:
這兩種方法的工做方式相同。他們首先查找名稱的setter(getter)方法,若是不存在setter(getter)方法,他們將在類中查找名爲名稱或_名稱的實例變量。而後給它賦值(取值)。無需經過對象指針直接訪問實例變量。
2)路徑
鍵路徑的深度是任意的,具體取決於對象圖。
鍵路徑不只能引用對象值,還能夠引用一些運算符來進行一些運算,例如獲取一組值的平均值或返回這組值中得最小值和最大值。
例如:NSNumber *count;
count = [garage valueForKeyPath:@"cars.@count"];
NSLog(@"We have %@ cars", count);
咱們將路徑「cars.@count」拆開,cars用於獲取cars屬性,它是來自garage的NSArray類型的值。接下來的部分是@count ,其中@符號意味着後面將進行一些運算。
和 cars@sun.mileage
最大值 cars@min.mileage
最小值 cars@max.mileage
3)總體操做
KVC很是棒的一點是,若是向NSArray請求一個鍵值,它實際上會查詢數組中得每一個對象來查找這個鍵值,而後將查詢結果打包到另外一個數組中並返回給你。這種方法也適用於經過鍵路徑訪問的對象內部的數組。
4)批處理
KVC包含兩個調用,能夠使用他們對對象進行批量更改。第一個調用是dictionaryWith-ValuesForKeys:。它接受一個字符串數組。該調用獲取一些鍵,對每一個鍵使用valueForKey:,而後爲鍵字符串和剛纔獲取的值構建一個字典。
一、Object-C有多繼承嗎?沒有的話用什麼代替?cocoa 中全部的類都是NSObject 的子類
多繼承在這裏是用protocol 委託代理 來實現的
你不用去考慮繁瑣的多繼承 ,虛基類的概念.
ood的多態特性 在 obj-c 中經過委託來實現.
二、Object-C有私有方法嗎?私有變量呢?
objective-c – 類裏面的方法只有兩種, 靜態方法和實例方法. 這彷佛就不是完整的面向對象了,按照OO的原則就是一個對象只暴露有用的東西. 若是沒有了私有方法的話, 對於一些小範圍的代碼重用就不那麼順手了. 在類裏面聲名一個私有方法
@interface Controller : NSObject { NSString *something; }
+ (void)thisIsAStaticMethod;
– (void)thisIsAnInstanceMethod;
@end
@interface Controller (private) -
(void)thisIsAPrivateMethod;
@end
@private能夠用來修飾私有變量
在Objective‐C中,全部實例變量默認都是私有的,全部實例方法默認都是公有的
三、關鍵字const什麼含義?
const意味着」只讀」,下面的聲明都是什麼意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前 兩個的做用是同樣,a是一個常整型數。第三個意味着a是一個指向常整型數的指針(也就是,整型數是不可修改的,但指針能夠)。第四個意思a是一個 指向整 型數的常指針(也就是說,指針指向的整型數是能夠修改的,但指針是不可修改的)。最後一個意味着a是一個指向常整型數的常指針(也就是說,指針指向的整型 數是不可修改的,同時指針也是不可修改的)。
結論:
?; 關鍵字const的做用是爲給讀你代碼的人傳達很是有用的信息, 實際上,聲明一個參數爲常量是爲了告訴了用戶這個參數的應用目的。若是你曾花 不少時間清理其它人留下的垃圾,你就會很快學會感謝這點多餘的信息。(固然,懂得用const的程序員不多會留下的垃圾讓別人來清理的。)
?; 經過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。
?; 合理地使用關鍵字const能夠使編譯器很天然地保護那些不但願被改變的參數,防止其被無心的代碼修改。簡而言之,這樣能夠減小bug的出現。
欲阻止一個變量被改變,能夠使用 const 關鍵字。在定義該 const 變量時,一般須要對它進行初
始化,由於之後就沒有機會再去改變它了;
(2)對指針來講,能夠指定指針自己爲 const,也能夠指定指針所指的數據爲 const,或兩者同時指定爲 const;
(3)在一個函數聲明中,const 能夠修飾形參,代表它是一個輸入參數,在函數內部不能改變其值;
(4)對於類的成員函數,若指定其爲 const 類型,則代表其是一個常函數,不能修改類的成員變量;
(5)對於類的成員函數,有時候必須指定其返回值爲 const 類型,以使得其返回值不爲「左值」。
四、關鍵字volatile有什麼含義?並給出三個不一樣例子?
一個定義爲volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到
這個變量時必須每次都當心地從新讀取這個變量的值,而不是使用保存在寄存器裏的備份。下面是volatile變量的幾個例子:
並行設備的硬件寄存器(如:狀態寄存器)
一箇中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
多線程應用中被幾個任務共享的變量
一個參數既能夠是const還能夠是volatile嗎?解釋爲何。
一個指針能夠是volatile 嗎?解釋爲何。
下面是答案:
是的。一個例子是隻讀的狀態寄存器。它是volatile由於它可能被意想不到地改變。它是const由於程序不該該試圖去修改它。
是的。儘管這並不很常見。一個例子是當一箇中服務子程序修該一個指向一個buffer的指針時。
static做用?
函數體內 static 變量的做用範圍爲該函數體,不一樣於 auto 變量,該變量的內存只被分配一次,
所以其值在下次調用時仍維持上次的值;
(2)在模塊內的 static 全局變量能夠被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
(3)在模塊內的 static 函數只可被這一模塊內的其它函數調用,這個函數的使用範圍被限制在聲明
它的模塊內;
(4)在類中的 static 成員變量屬於整個類所擁有,對類的全部對象只有一份拷貝;
(5)在類中的 static 成員函數屬於整個類所擁有,這個函數不接收 this 指針,於是只能訪問類的static 成員變量。
六、#import和#include的區別,@class表明什麼?
@class通常用於頭文件中須要聲明該類的某個實例變量的時候用到,在m文件中仍是須要使用#import
而#import比起#include的好處就是不會引發重複包含
七、線程和進程的區別?
進程和線程都是由操做系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的併發性。
進 程和線程的主要差異在於它們是不一樣的操做系統資源管理方式。進程有獨立的地址空間,一個進程崩潰後,在保護模式下不會對其它進程產生影響,而線程 只是一 個進程中的不一樣執行路徑。線程有本身的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,因此多進程的程序要比多線程的程 序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行而且又要共享某些變量的併發操做,只能用線程,不能用進程。
八、堆和棧的區別?
管理方式:對於棧來說,是由編譯器自動管理,無需咱們手工控制;對於堆來講,釋放工做由程序員控制,容易產生memory leak。
申請大小:
棧: 在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在 WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就肯定的常數),若是申請的空間超過棧的剩餘空間時,將提示overflow。因 此,能從棧得到的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是因爲系統是用鏈表來存儲的空閒內存地址的,天然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。因而可知,堆得到的空間比較靈活,也比較大。
碎片問題:對於堆來說,頻繁的new/delete勢必會形成內存空間的不連續,從而形成大量的碎片,使程序效率下降。對於棧來說,則不會存在這個問題,由於棧是先進後出的隊列,他們是如此的一一對應,以致於永遠都不可能有一個內存塊從棧中間彈出
分配方式:堆都是動態分配的,沒有靜態分配的堆。棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,好比局部變量的分配。動態分配由alloca函數進行分配,可是棧的動態分配和堆是不一樣的,他的動態分配是由編譯器進行釋放,無需咱們手工實現。
分配效率:棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是C/C++函數庫提供的,它的機制是很複雜的。
九、Object-C的內存管理?
1.當你使用new,alloc和copy方法建立一個對象時,該對象的保留計數器值爲1.當你再也不使用該對象時,你要負責向該對象發送一條release或autorelease消息.這樣,該對象將在使用壽命結束時被銷燬.
2.當你經過任何其餘方法得到一個對象時,則假設該對象的保留計數器值爲1,並且已經被設置爲自動釋放,你不須要執行任何操做來確保該對象被清理.若是你打算在一段時間內擁有該對象,則須要保留它並確保在操做完成時釋放它.
3.若是你保留了某個對象,你須要(最終)釋放或自動釋放該對象.必須保持retain方法和release方法的使用次數相等.
十、爲何不少內置的類,如TableViewController的delegate的屬性是assign不是retain?
循環引用
全部的引用計數系統,都存在循環應用的問題。例以下面的引用關係:
對象a建立並引用到了對象b.
對象b建立並引用到了對象c.
對象c建立並引用到了對象b.
這時候b和c的引用計數分別是2和1。當a再也不使用b,調用release釋放對b的全部權,由於c還引用了b,因此b的引用計數爲1,b不會被釋放。b不釋放,c的引用計數就是1,c也不會被釋放。今後,b和c永遠留在內存中。
這 種狀況,必須打斷循環引用,經過其餘規則來維護引用關係。好比,咱們常見的delegate每每是assign方式的屬性而不是retain方式 的屬 性,賦值不會增長引用計數,就是爲了防止delegation兩端產生沒必要要的循環引用。若是一個UITableViewController 對象a通 過retain獲取了UITableView對象b的全部權,這個UITableView對象b的delegate又是a,若是這個delegate是 retain方式的,那基本上就沒有機會釋放這兩個對象了。本身在設計使用delegate模式時,也要注意這點。
十一、定義屬性時,什麼狀況使用copy、assign、retain?
assign用於簡單數據類型,如NSInteger,double,bool,
retain和copy用於對象,
copy用於當a指向一個對象,b也想指向一樣的對象的時候,若是用assign,a若是釋放,再調用b會crash,若是用copy 的方式,a和b各自有本身的內存,就能夠解決這個問題。
retain 會使計數器加一,也能夠解決assign的問題。
另外:atomic和nonatomic用來決定編譯器生成的getter和setter是否爲原子操做。在多線程環境下,原子操做是必要的,不然有可能引發錯誤的結果。
加了atomic,setter函數會變成下面這樣:
if (property != newValue) {
[property release];
property = [newValue retain];
}
十二、對象是何時被release的?
引用計數爲0時。
autorelease 實際上只是把對release的調用延遲了,對於每個Autorelease,系統只是把該Object放入了當前的 Autorelease pool中,當該pool被釋放時,該pool中的全部Object會被調用Release。對於每個Runloop,系統會 隱式建立一個Autorelease pool,這樣全部的release pool會構成一個象CallStack同樣的一個棧式結構,在每個 Runloop結束時,當前棧頂的Autorelease pool會被銷燬,這樣這個pool裏的每一個Object(就是autorelease的對 象)會被release。那什麼是一個Runloop呢?一個UI事件,Timer call, delegate call, 都會是一個新的 Runloop
1三、iOS有沒有垃圾回收?
Objective-C 2.0也是有垃圾回收機制的,可是隻能在Mac OS X Leopard 10.5 以上的版本使用。
1四、tableView的重用機制?
查 看UITableView頭文件,會找到NSMutableArray* visiableCells,和 NSMutableDictnery* reusableTableCells兩個結構。visiableCells內保存當前顯示的 cells,reusableTableCells保存可重用的cells。
TableView顯示之 初,reusableTableCells爲空,那麼 tableView dequeueReusableCellWithIdentifier:CellIdentifier返回nil。開始的cell都 是經過 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 來建立,並且cellForRowAtIndexPath只是調用最大顯示cell數的次數。
好比:有100條數據,iPhone一屏最多顯示10個cell。程序最開始顯示TableView的狀況是:
1. 用 [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 建立10次cell,並給cell指定一樣的重用標識(固然,能夠爲不一樣顯示類型的cell指定不一樣的標識)。而且10個cell所有都加入到 visiableCells數組,reusableTableCells爲空。
2.向下拖動tableView,當cell1徹底移出屏 幕,而且cell11(它也是alloc出來的,緣由同上)徹底顯示出來的時候。 cell11加入到visiableCells,cell1移出visiableCells,cell1加入到reusableTableCells。
3. 接着向下拖動tableView,由於reusableTableCells中已經有值,因此,當須要顯示新的 cell,cellForRowAtIndexPath再次被調用的時 候,tableView dequeueReusableCellWithIdentifier:CellIdentifier,返回cell1。 cell1加入到visiableCells,cell1移出reusableTableCells;cell2移出 visiableCells,cell2加入到reusableTableCells。以後再須要顯示的Cell就能夠正常重用了。
1五、ViewController 的loadView、viewDidLoad、viewDidUnload分別是何時調用的,在自定義ViewCointroller時在這幾個函數中應該作什麼工做?
由init、loadView、viewDidLoad、viewDidUnload、dealloc的關係提及
init方法
在init方法中實例化必要的對象(聽從LazyLoad思想)
init方法中初始化ViewController自己
loadView方法
當view須要被展現而它倒是nil時,viewController會調用該方法。不要直接調用該方法。
若是手工維護views,必須重載重寫該方法
若是使用IB維護views,必須不能重載重寫該方法
loadView和IB構建view
你 在控制器中實現了loadView方法,那麼你可能會在應用運行的某個時候被內存管理控制調用。 若是設備內存不足的時候, view 控制器會 收到 didReceiveMemoryWarning的消息。 默認的實現是檢查當前控制器的view是否在使用。若是它的view不在當前正在使用的 view hierarchy裏面,且你的控制器實現了loadView方法,那麼這個view將被release, loadView方法將被再次調用 來建立一個新的view。
viewDidLoad方法
viewDidLoad 此方法只有當view從nib文件初始化的時候才被調用。
重載重寫該方法以進一步定製view
在iPhone OS 3.0及以後的版本中,還應該重載重寫viewDidUnload來釋放對view的任何索引
viewDidLoad後調用數據Model
viewDidUnload方法
當系統內存吃緊的時候會調用該方法(注:viewController沒有被dealloc)
內存吃緊時,在iPhone OS 3.0以前didReceiveMemoryWarning是釋放無用內存的惟一方式,可是OS 3.0及之後viewDidUnload方法是更好的方式
在該方法中將全部IBOutlet(不管是property仍是實例變量)置爲nil(系統release view時已經將其release掉了)
在 該方法中釋放其餘與view有關的對象、其餘在運行時建立(但非系統必須)的對象、在viewDidLoad中被建立的對象、緩存數據 等 release對象後,將對象置爲nil(IBOutlet只須要將其置爲nil,系統release view時已經將其release掉了)
通常認爲viewDidUnload是viewDidLoad的鏡像,由於當view被從新請求時,viewDidLoad還會從新被執行
viewDidUnload中被release的對象必須是很容易被從新建立的對象(好比在viewDidLoad或其餘方法中建立的對象),不要release用戶數據或其餘很難被從新建立的對象
dealloc方法
viewDidUnload和dealloc方法沒有關聯,dealloc仍是繼續作它該作的事情
1六、ViewController的didReceiveMemoryWarning是在何時調用的?默認的操做是什麼?
當程序接到內存警告時View Controller將會收到這個消息:didReceiveMemoryWarning
從iOS3.0開始,不須要重載這個函數,把釋放內存的代碼放到viewDidUnload中去。
這個函數的默認實現是:檢查controller是否能夠安全地釋放它的view(這裏加粗的view指的是controller的view屬性),好比view自己沒有superview而且能夠被很容易地重建(從nib或者loadView函數)。
若是view能夠被釋放,那麼這個函數釋放view並調用viewDidUnload。
你能夠重載這個函數來釋放controller中使用的其餘內存。但要記得調用這個函數的super實現來容許父類(通常是UIVIewController)釋放view。
若是你的ViewController保存着view的子view的引用,那麼,在早期的iOS版本中,你應該在這個函數中來釋放這些引用。而在iOS3.0或更高版本中,你應該在viewDidUnload中釋放這些引用。
1七、列舉Cocoa中常見的集中多線程的實現,並談談多線程安全的幾種解決辦法,通常什麼地方會用到多線程?
NSThread,GCD等。儘可能用上層分裝好的方法去實現多線程而不是手動調用NSThread。
1八、怎麼理解MVC,在Cocoa中MVC是怎麼實現的?
Model: 表明你的應用程序是什麼(不是怎麼展示)
Controller: 控制你的Model怎麼展示給用戶(UI邏輯)
View: Controller的奴隸。。。
1 Model,Controller,View相互通信的規則:
Controller能夠直接和Model通訊
Controller也能夠直接和View通訊
Model和View永遠不能直接通訊
iOS中View和Controller的通訊是透明和固定的,主要經過outlet和action實現
View使用Delegate接口和Controller同步信息
View不直接和數據通訊,使用dataSource接口從Controller處獲取數據
View的delegate和dataSource通常就是Controller
Controller負責爲View翻譯和格式化Model的數據
Model使用Notification & KVO的方式分發數據更新信息,Controller能夠有選擇的監聽本身感興趣的信息。
View也能夠監聽廣播信息,但通常不是Model發出的信息
一個完整的App就是不少MVC的集合
1九、delegate和notification區別,分別在什麼狀況下使用?
Delegate:
消息的發送者(sender)告知接收者(receiver)某個事件將要發生,delegate贊成然而後發送者響應事件,delegate機制使得接收者能夠改變發送者的行爲。一般發送者和接收者的關係是直接的一對多的關係。
Notification:
消息的發送者告知接收者事件已經發生或者將要發送,僅此而已,接收者並不能反過來影響發送者的行爲。一般發送者和接收者的關係是間接的多對多關係。
1. 效率確定是delegate比nsnotification高。
2. delegate 方法比notification更加直接,最典型的特徵是,delegate方法每每須要關注返回值,也就是 delegate方法 的結果。好比-windowShouldClose:,須要關心返回的是yes仍是no。因此delegate方法每每包含should這個很傳神的詞。 也就是比如你作個人delegate,我會問你我想關閉窗口你願意嗎?你須要給我一個答案,我根據你的答案來決定如何作下一步。相反 的,notification最大的特點就是不關心接受者的態度,我只管把通告放出來,你接受不接受就是你的事情,同時我也不關心結果。因此 notification每每用did這個詞彙,好比NSWindowDidResizeNotification,那麼nswindow對象放出這個 notification後就什麼都無論了也不會等待接受者的反應。
1)兩個模塊之間聯繫不是很緊密,就用notification傳值,例如多線程之間傳值用notificaiton。
2)delegate 只是一種較爲簡單的回調,且主要用在一個模塊中,例如底層功能完成了,須要把一些值傳到上層去,就事先把上層的函數經過 delegate傳到底層,而後在底層call這個delegate,它們都在一個模塊中,完成一個功能,例如 說 NavgationController 從 B 界面到A 點返回按鈕 (調用popViewController方法) 能夠用delegate 比較好。
20、self.跟self什麼區別?
2一、id、nil表明什麼?
id 和void *並不是徹底同樣。在上面的代碼中,id是指向struct objc_object的一個指針,這個意思基本上是說,id是一個指 向任何 一個繼承了Object(或者NSObject)類的對象。須要注意的是id是一個指針,因此你在使用id的時候不須要加星號。好比id foo=nil 定義了一個nil指針,這個指針指向NSObject的一個任意子類。而id *foo=nil則定義了一個指針,這個指針指向另外一個指針,被指向的這個 指針指向NSObject的一個子類。
nil和C語言的NULL相同,在objc/objc.h中定義。nil表示一個Objctive-C對象,這個對象的指針指向空(沒有東西就是空)。
首字母大寫的Nil和nil有一點不同,Nil定義一個指向空的類(是Class,而不是對象)。
SEL是「selector」的一個類型,表示一個方法的名字
Method(咱們常說的方法)表示一種類型,這種類型與selector和實現(implementation)相關
IMP定義爲 id (*IMP) (id, SEL, …)。這樣說來, IMP是一個指向函數的指針,這個被指向的函數包括id(「self」指針),調用的SEL(方法名),再加上一些其餘參數.說白了IMP就是實現方法。
2二、內存管理 Autorelease、retain、copy、assign的set方法和含義?
1,你初始化(alloc/init)的對象,你須要釋放(release)它。例如:
NSMutableArray aArray = [[NSArray alloc] init]; 後,須要 [aArray release];
2,你retain或copy的,你須要釋放它。例如:
[aArray retain] 後,須要 [aArray release];
3,被傳遞(assign)的對象,你須要斟酌的retain和release。例如:
obj2 = [[obj1 someMethod] autorelease];
對象2接收對象1的一個自動釋放的值,或傳遞一個基本數據類型(NSInteger,NSString)時:你或但願將對象2進行retain,以防止它在被使用以前就被自動釋放掉。可是在retain後,必定要在適當的時候進行釋放。
關於索引計數(Reference Counting)的問題
retain值 = 索引計數(Reference Counting)
NSArray 對象會retain(retain值加一)任何數組中的對象。當NSArray被卸載(dealloc)的時候,全部數組中的對象會 被 執行一次釋放(retain值減一)。不只僅是NSArray,任何收集類(Collection Classes)都執行相似操做。例如 NSDictionary,甚至UINavigationController。
Alloc/init創建的對象,索引計數爲1。無需將其再次retain。
[NSArray array]和[NSDate date]等「方法」創建一個索引計數爲1的對象,可是也是一個自動釋放對象。因此是本地臨時對象,那麼無所謂了。若是是打算在全Class中使用的變量(iVar),則必須retain它。
缺省的類方法返回值都被執行了「自動釋放」方法。(*如上中的NSArray)
在類中的卸載方法「dealloc」中,release全部未被平衡的NS對象。(*全部未被autorelease,而retain值爲1的)
2三、類別的做用?
有時咱們須要在一個已經定義好的類中增長一些方法,而不想去重寫該類。好比,當工程已經很大,代碼量比較多,或者類中已經包住不少方法,已經有其餘代碼調用了該類建立對象並使用該類的方法時,能夠使用類別對該類擴充新的方法。
注意:類別只能擴充方法,而不能擴充成員變量。
2四、委託(舉例)
委託代理(degegate),顧名思義,把某個對象要作的事情委託給別的對象去作。那麼別的對象就是這個對象的代理,代替它來打理要作的事。反映到程序中,首先要明確一個對象的委託方是哪一個對象,委託所作的內容是什麼。
委託機制是一種設計模式,在不少語言中都用到的,這只是個通用的思想,網上會有不少關於這方面的介紹。
那麼在蘋果開發過程當中,用到委託的程序實現思想以下,我主要拿如何在視圖之間傳輸信息作個例子。
譬如:在兩個頁面(UIIview視圖對象)實現傳值,用委託(delegate)能夠很好作到!
方法:
類A
@interface A:UIView
id transparendValueDelegate;
@property(nomatic, retain) id transparendValueDelegate;
@end
@implemtion A
@synthesize transparendValueDelegate
-(void)Function
{
NSString* value = @"hello";
//讓代理對象執行transparendValue動做
[transparendValueDelegate transparendValue: value];
}
@end
類B
@interface B:UIView
NSString* value;
@end
@implemtion B
-(void)transparendValue:(NSString*)fromValue
{
value = fromValue;
NSLog(@"the value is %@ ",value);
}
@end
//下面的設置A代理委託對象爲B
//在定義A和B類對象處:
A* a = [[A alloc] init];
B* b = [[B alloc] init];
a. transparendValueDelegate = b;//設置對象a代理爲對象b
這樣在視圖A和B之間能夠經過委託來傳值!
2五、retainCount?
26..屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什麼做用,在那種狀況下用
assign:指定setter方法用簡單的賦值,這是默認操做。你能夠對標量類型(如int)使用這個屬性。你能夠想象一個float,它不是一個對象,因此它不能retain、copy。
retain:指定retain應該在後面的對象上調用,前一個值發送一條release消息。你能夠想象一個NSString實例,它是一個對象,並且你可能想要retain它。
copy:指定應該使用對象的副本(深度複製),前一個值發送一條release消息。基本上像retain,可是沒有增長引用計數,是分配一塊新的內存來放置它。
readonly:將只生成getter方法而不生成setter方法(getter方法沒有get前綴)。
readwrite:默認屬性,將生成不帶額外參數的getter和setter方法(setter方法只有一個參數)。
atomic:對於對象的默認屬性,就是setter/getter生成的方法是一個原子操做。若是有多個線程同時調用setter的話,不會出現某一個線程執行setter所有語句以前,另外一個線程開始執行setter的狀況,相關於方法頭尾加了鎖同樣。
nonatomic:不保證setter/getter的原子性,多線程狀況下數據可能會有問題。
27.類變量的@protected ,@private ,@public ,@package聲明各有什麼含義
Objective-C 對存取權限的設定。也是變量的做用域。
protected 該類和全部的子類中的方法能夠直接訪問這樣的變量,這是默認的。
private — 該類中的方法能夠訪問這樣的變量,子類不能夠。 public — 除了本身和子類中的方法外,也能夠被其餘類或者其餘模塊中的方法所訪問。開放性最大。 package — 對於64位圖像,這樣的成員變量能夠在實現這個類的圖像中隨意訪問。
28.淺拷貝和深拷貝區別是什麼
簡單的來講就是,在有指針的狀況下,淺拷貝只是增長了一個指針指向已經存在的內存,而深拷貝就是增長一個指針而且申請一個新的內存,使這個增長的指針指向這個新的內存,採用深拷貝的狀況下,釋放內存的時候就不會出如今淺拷貝時重複釋放同一內存的錯誤
29.Cocoa中與虛基類的概念麼?怎麼簡潔的實現
30.NSString 和 NSMutableString 有什麼區別
NSString至關於一個const char* 不能夠改變。
而 NSMutableString至關於 char* 能夠改變內部的內容。
31.自動釋放池跟GC有什麼區別?iPhone上有GC麼?[pool release] 和[pool drain]有什麼區別
」Autorelease Pools」(自動釋放池)在應用中的使用技巧。
1,Autorelease Pools概要
一 個」Autorelease Pool」實例中「包含」其它各類調用了」autorelease」方法的對象。當它釋放時,其中全部被管理對象都 會收 到」relrease」的消信。注意,同一個對象能夠被屢次調用」autorelease」方法,並能夠放到同一個」Autorelease Pool」 中。引入這個自動釋放池機制,對象的」autorelease」方法代替」relrease」方法能夠延長它的生命週期,直接到當 前」Autorelrease Pool」釋放。若是想讓此對象的生命週期超過」Autorelease Pool」,還能夠再次」retain」,呵 呵,有意思吧?且讓我慢慢道來。
Cocoa老是認爲當前至少有一個」Autorelease Pool」對象是可用的。若此對象並不存在,你調用的」autorelease」的全部對象都不會被自動釋放掉,可想而知,形成內存泄露。Cocoa把這個錯誤信息寫入日誌??僅僅是爲了之後分析。
你 能夠用」alloc」與」init」方法建立一個」NSAutoreleasePool」對象,而且能夠調用」release」或」drain」 (」release」與」drain」的區別是」drain」在有GC的環境中會引發GC回收操做,」release」反之。但在非GC環境中,二者相 同。官方的說法是爲了程序的兼容性,應該考慮用」drain」代替」release」,)方法來回收它(調用它的」autorelease」 或」retain」方法會引發異常)。在一個完整的上下文最後」Autorelease Pool」對象應該被」release」掉(在方法內或一段循環 體內建立的」Autorelease Pool」對象)。
「Autorelease Pools」的全部實例在棧中管理(咱們暫時叫他 「自動釋放池棧」),而且它們是能夠被嵌套的(父生子,子生孫。。。子 子孫 孫 ^_^)。例如,當咱們建立一個」Autorelease Pool」對象後,它就被自動放到「自動釋放池棧」的棧頂。當本池對象回收時,它就隨之從 這個棧中POP掉。那麼也就是說,當任何一個對象調用」autorelease」方法後,它會被放入當前線程中當前棧頂的自動釋放池中。
接 下來咱們聊聊」Autorelease Pools」的嵌套問題。在你的應用中,你能夠任意多的建立」Autorelease Pool」對象, 而這些 對象被當前線程的「自動釋放池棧」所管理。那麼除了一個接一個的順序建立並銷燬它的狀況外,還有一種使用方式,就是嵌套式的建立與使用。例如:在你的主函 數建立了一個」autorelease pool」,而後又調用了建立了」autorelease pool」實例的其它方法;或是在外循環中建立 了」Autorelease Pool」的實例,而內循環中也作了相同的事情。有意思吧,呵呵,嵌套的機制使父Pool實例釋放後,它的全部子Pool也 將釋放。但這裏還存在一些反作用,後續文章會詳細討論。
「Application kit」在一個事件循環裏會自動建立一個」autorelease pool」。像鼠標鍵的按下與釋放,因此你編寫的代碼一般不須要考慮太多這方面的事情。固然,有如下三種狀況你會建立與銷燬本身的Pool實例:
1,應用不是基於」Application Kit」,像」Command-line tool」,由於它並無內置的」autorelease pools」的支持。
2,建立線程,你必需在線程開始時建立一個」Autorelease Pool」實例。反之,會形成內存池露(會在之後的文章詳細說明線程與池的技巧)。
3,一個循環內建立了太多的臨時對象,你應該爲他們建立一個」Autorelease Pool」對象,並在下次循還前銷燬它們。
2,自動釋放池中的」Non-AppKit」應用
在」Non- AppKit」應用中使用自動釋放池的機制實際上是至關簡單的事情。你僅僅須要在main()起始處創 建」Autorelease Pool」 對象,並在結尾處釋放掉它。就像在Xcode的Foundation Tool的建立模版裏寫的同樣。這個確保你在應用生命週期內至少有一 個」Autorelease Pool」是可用的。可是,這也使全部在此期間的全部」autorelease」的對象都必需在應用結束後才被釋放。這也許 會引發在應用的使用中不斷的增加,因此,你仍然考慮在不一樣的做用域建立新的」Autorelease Pool」。
大多應用中都存在各類級別的循環機制。在這些應用中,你能夠在每一個循環內的開頭建立一個」Autorelease Pool」對象,並在結尾處釋放掉它。
例如:
void main()
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSArray *args = [[NSProcessInfo processInfo] arguments];
unsigned count, limit = [args count];
for (count = 0; count < limit; count++)
{
NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
NSString *fileContents;
NSString *fileName;
fileName = [args objectAtIndex:count];
fileContents = [[[NSString alloc] initWithContentsOfFile:fileName] autorelease];
// this is equivalent to using stringWithContentsOfFile:
[loopPool release];
}
[pool drain];
exit (EXIT_SUCCESS);
}
在 命令行中處理全部以參數傳來的文件。一次循環處理一個文件。在循環的開頭建立一個」NSAutoreleasePool」對象,並在循環結束時釋 放掉。 所以,任何在其中建立並調用「autorelease」的對象都將添加到這個Pool實例中,當本池被釋放後,這些對象也將被回收。注意,任何在做用域內 建立的」autoreleased」對象(像」fileName」),雖然並無顯示的調用」autorelease」方法,但都將被當前池所管理並釋 放。
32.C和obj-c 如何混用
1)obj-c的編譯器處理後綴爲m的文件時,能夠識別obj-c和c的代碼,處理mm文件能夠識別obj-c,c,c++代碼,但cpp文件必須只能用c/c++代碼,並且cpp文件include的頭文件中,也不能出現obj-c的代碼,由於cpp只是cpp
2)在mm文件中混用cpp直接使用便可,因此obj-c混cpp不是問題
3)在cpp中混用obj-c其實就是使用obj-c編寫的模塊是咱們想要的。
若是模塊以類實現,那麼要按照cpp class的標準寫類的定義,頭文件中不能出現obj-c的東西,包括#import cocoa的。實現文件中,即類的實現代碼中能夠使用obj-c的東西,能夠import,只是後綴是mm。
若是模塊以函數實現,那麼頭文件要按c的格式聲明函數,實現文件中,c++函數內部能夠用obj-c,但後綴仍是mm或m。
總 結:只要cpp文件和cpp include的文件中不包含obj-c的東西就能夠用了,cpp混用obj-c的關鍵是使用接口,而不能直接使用 實現代 碼,實際上cpp混用的是obj-c編譯後的o文件,這個東西實際上是無差異的,因此能夠用。obj-c的編譯器支持cpp
33.響應者鏈是什麼
響 應者鏈是Application Kit事件處理架構的中心機制。它由一系列連接在一塊兒的響應者對象組成,事件或者動做消息能夠沿着這些對象進行 傳 遞。如圖6-20顯示的那樣,若是一個響應者對象不能處理某個事件或動做-也就是說,它不響應那個消息,或者不認識那個事件,則將該消息從新發送給鏈中的 下一個響應者。消息沿着響應者鏈向上、向更高級別的對象傳遞,直到最終被處理(若是最終仍是沒有被處理,就會被拋棄)。
當 Application Kit在應用程序中構造對象時,會爲每一個窗口創建響應者鏈。響應者鏈中的基本對象是NSWindow對象及其視圖層次。 在視圖層次中級別較低的視圖將比級別更高的視圖優先得到處理事件或動做消息的機會。NSWindow中保有一個第一響應者的引用,它一般是當前窗口中處於 選擇狀態的視圖,窗口一般把響應消息的機會首先給它。對於事件消息,響應者鏈一般以發生事件的窗口對應的NSWindow對象做爲結束,雖然其它對象也可 以做爲下一個響應者被加入到NSWindow對象的後面。
34..UIscrollVew用到了什麼設計模式?還能再foundation庫中找到相似的嗎?
組合模式composition,全部的container view都用了這個模式
觀察者模式observer,全部的UIResponder都用了這個模式。
模板(Template)模式,全部datasource和delegate接口都是模板模式的典型應用
33. .timer的間隔週期準嗎?爲何?怎樣實現一個精準的timer?
NSTimer能夠精確到50-100毫秒.
NSTimer不是絕對準確的,並且中間耗時或阻塞錯過下一個點,那麼下一個點就pass過去了
此份面試題包含40個題目,是如今網上能搜索到的一個比較熱的一份,可是答案並非很詳細和完整,基本答案來着cocoaChina,和一些本身的補充。
34.Difference between shallow copy and deep copy?
淺複製和深複製的區別?
答案:淺層複製:只複製指向對象的指針,而不復制引用對象自己。
深層複製:複製引用對象自己。
意思就是說我有個A對象,複製一份後獲得A_copy對象後,對於淺複製來講,A和A_copy指向的是同一個內存資源,複製的只不過是是一個指針,對象自己資源
仍是隻有一份,那若是咱們對A_copy執行了修改操做,那麼發現A引用的對象一樣被修改,這其實違背了咱們複製拷貝的一個思想。深複製就好理解了,內存中存在了
兩份獨立對象自己。
用網上一哥們通俗的話將就是:
淺複製比如你和你的影子,你完蛋,你的影子也完蛋
深複製比如你和你的克隆人,你完蛋,你的克隆人還活着。
35.What is advantage of categories? What is difference between implementing a category and inheritance?
類別的做用?繼承和類別在實現中有何區別?
答案:category 能夠在不獲悉,不改變原來代碼的狀況下往裏面添加新的方法,只能添加,不能刪除修改。
而且若是類別和原來類中的方法產生名稱衝突,則類別將覆蓋原來的方法,由於類別具備更高的優先級。
類別主要有3個做用:
(1)將類的實現分散到多個不一樣文件或多個不一樣框架中。
(2)建立對私有方法的前向引用。
(3)向對象添加非正式協議。
繼承能夠增長,修改或者刪除方法,而且能夠增長屬性。
36.Difference between categories and extensions?
類別和類擴展的區別。
答案:category和extensions的不一樣在於後者能夠添加屬性。另外後者添加的方法是必需要實現的。
extensions能夠認爲是一個私有的Category。
37.Difference between protocol in objective c and interfaces in java?
oc中的協議和java中的接口概念有何不一樣?
答案:OC中的代理有2層含義,官方定義爲 formal和informal protocol。前者和Java接口同樣。
informal protocol中的方法屬於設計模式考慮範疇,不是必須實現的,可是若是有實現,就會改變類的屬性。
其實關於正式協議,類別和非正式協議我很早前學習的時候大體看過,也寫在了學習教程裏
「非正式協議概念其實就是類別的另外一種表達方式「這裏有一些你可能但願實現的方法,你能夠使用他們更好的完成工做」。
這個意思是,這些是可選的。好比我門要一個更好的方法,咱們就會申明一個這樣的類別去實現。而後你在後期能夠直接使用這些更好的方法。
這麼看,總以爲類別這玩意兒有點像協議的可選協議。"
如今來看,其實protocal已經開始對二者都統一和規範起來操做,由於資料中說「非正式協議使用interface修飾「,
如今咱們看到協議中兩個修飾詞:「必須實現(@requied)」和「可選實現(@optional)」。
38.What are KVO and KVC?
答案:kvc:鍵 - 值編碼是一種間接訪問對象的屬性使用字符串來標識屬性,而不是經過調用存取方法,直接或經過實例變量訪問的機制。
不少狀況下能夠簡化程序代碼。apple文檔其實給了一個很好的例子。
kvo:鍵值觀察機制,他提供了觀察某一屬性變化的方法,極大的簡化了代碼。
具體用看到嗯哼用到過的一個地方是對於按鈕點擊變化狀態的的監控。
好比我自定義的一個button
[cpp]
[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
{
([keyPath isEqualToString:@"highlighted"] ) {
[self setNeedsDisplay];
}
}
對於系統是根據keypath去取的到相應的值發生改變,理論上來講是和kvc機制的道理是同樣的。
對於kvc機制如何經過key尋找到value:
「當 經過KVC調用對象時,好比:[self valueForKey:@」someKey」]時,程序會自動試圖經過幾種不一樣的方式解析這個調 用。首先 查找對象是否帶有 someKey 這個方法,若是沒找到,會繼續查找對象是否帶有someKey這個實例變量(iVar),若是尚未找到,程序會繼續 試圖調用 -(id) valueForUndefinedKey:這個方法。若是這個方法仍是沒有被實現的話,程序會拋出一個 NSUndefinedKeyException異常錯誤。
(cocoachina.com注:Key-Value Coding查找方法 的時候,不只僅會查找someKey這個方法,還會查找 getsomeKey這個方法,前面加一個get,或者_someKey以及_getsomeKey這幾種形式。同時,查找實例變量的時候也會不只僅查找 someKey這個變量,也會查找_someKey這個變量是否存在。)
設計valueForUndefinedKey:方法的主要目的是當你使用-(id)valueForKey方法從對象中請求值時,對象可以在錯誤發生前,有最後的機會響應這個請求。這樣作有不少好處,下面的兩個例子說明了這樣作的好處。「
來至cocoa,這個說法應該挺有道理。
由於咱們知道button倒是存在一個highlighted實例變量.所以爲什麼上面咱們只是add一個相關的keypath就好了,
能夠按照kvc查找的邏輯理解,就說的過去了。
39.What is purpose of delegates?
代理的做用?
答案:代理的目的是改變或傳遞控制鏈。容許一個類在某些特定時刻通知到其餘類,而不須要獲取到那些類的指針。能夠減小框架複雜度。
另一點,代理能夠理解爲java中的回調監聽機制的一種相似。
40.What are mutable and immutable types in Objective C?
oc中可修改和不能夠修改類型。
答案:可修改不可修改的集合類。這個我我的簡單理解就是可動態添加修改和不可動態添加修改同樣。
好比NSArray和NSMutableArray。前者在初始化後的內存控件就是固定不可變的,後者能夠添加等,能夠動態申請新的內存空間。
41.When we call objective c is runtime language what does it mean?
咱們說的oc是動態運行時語言是什麼意思?
答案:多態。 主要是將數據類型的肯定由編譯時,推遲到了運行時。
這個問題其實淺涉及到兩個概念,運行時和多態。
簡單來講,運行時機制使咱們直到運行時纔去決定一個對象的類別,以及調用該類別對象指定方法。
多態:不一樣對象以本身的方式響應相同的消息的能力叫作多態。意思就是假設生物類(life)都用有一個相同的方法-eat;
那人類屬於生物,豬也屬於生物,都繼承了life後,實現各自的eat,可是調用是咱們只需調用各自的eat方法。
也就是不一樣的對象以本身的方式響應了相同的消息(響應了eat這個選擇器)。
所以也能夠說,運行時機制是多態的基礎?~~~
42.what is difference between NSNotification and protocol?
通知和協議的不一樣之處?
答案:協議有控制鏈(has-a)的關係,通知沒有。
首先我一開始也不太明白,什麼叫控制鏈(專業術語了~)。可是簡單分析下通知和代理的行爲模式,咱們大體能夠有本身的理解
簡單來講,通知的話,它能夠一對多,一條消息能夠發送給多個消息接受者。
代理按咱們的理解,到不是直接說不能一對多,好比咱們知道的明星經濟代理人,不少時候一個經濟人負責好幾個明星的事務。
只是對於不一樣明星間,代理的事物對象都是不同的,一一對應,不可能說明天要處理A明星要一個發佈會,代理人發出處理髮佈會的消息後,別稱B的
發佈會了。可是通知就不同,他只關心發出通知,而不關心多少接收到感興趣要處理。
所以控制鏈(has-a從英語單詞大體能夠看出,單一擁有和可控制的對應關係。
43.What is push notification?
什麼是推送消息?
答案:太簡單,不做答~~~~~~~~~~
這是cocoa上的答案。
其實到不是說太簡單,只是太泛泛的一個概念的東西。就比如說,什麼是人。
推送通知更是一種技術。
簡單點就是客戶端獲取資源的一種手段。
普通狀況下,都是客戶端主動的pull。
推送則是服務器端主動push。
44.Polymorphism?
關於多態性
答案:多態,子類指針能夠賦值給父類。
這個題目其實能夠出到一切面向對象語言中,
所以關於多態,繼承和封裝基本最好都有個自我意識的理解,也並不是必定要把書上資料上寫的能背出來。
最重要的是轉化成自我理解。
45.Singleton?
對於單例的理解
答案:11,12題目其實出的有點泛泛的感受了,可能說是編程語言須要或是必備的基礎。
基本能用熟悉的語言寫出一個單例,以及能夠運用到的場景或是你編程中碰到過運用的此種模式的框架類等。
進一步點,考慮下如何在多線程訪問單例時的安全性。
46.What is responder chain?
說說響應鏈
答案: 事件響應鏈。包括點擊事件,畫面刷新事件等。在視圖棧內從上至下,或者從下之上傳播。
能夠說點事件的分發,傳遞以及處理。具體能夠去看下touch事件這塊。由於問的太抽象化了
嚴重懷疑題目出到越後面就越籠統。
47.Difference between frame and bounds?
frame和bounds有什麼不一樣?
答案:frame指的是:該view在父view座標系統中的位置和大小。(參照點是父親的座標系統)
bounds指的是:該view在自己座標系統中 的位置和大小。(參照點是自己座標系統)
48.Difference between method and selector?
方法和選擇器有何不一樣?
答案:selector是一個方法的名字,method是一個組合體,包含了名字和實現.
詳情能夠看apple文檔。
49.Is there any garbage collection mechanism in Objective C.?
OC的垃圾回收機制?
答案: OC2.0有Garbage collection,可是iOS平臺不提供。
通常咱們瞭解的objective-c對於內存管理都是手動操做的,可是也有自動釋放池。
可是差了大部分資料,貌似不要和arc機制搞混就行了。
求更多~~
50.NSOperation queue?
答案:存放NSOperation的集合類。
操做和操做隊列,基本能夠當作java中的線程和線程池的概念。用於處理ios多線程開發的問題。
網上部分資料提到一點是,雖然是queue,可是卻並非帶有隊列的概念,放入的操做並不是是按照嚴格的先進現出。
這邊又有個疑點是,對於隊列來講,先進先出的概念是Afunc添加進隊列,Bfunc緊跟着也進入隊列,Afunc先執行這個是必然的,
可是Bfunc是等Afunc徹底操做完之後,B纔開始啓動而且執行,所以隊列的概念離亂上有點違背了多線程處理這個概念。
可是轉念一想其實能夠參考銀行的取票和叫號系統。
所以對於A比B先排隊取票可是B率先執行完操做,咱們亦然能夠感性認爲這仍是一個隊列。
可是後來看到一票關於這操做隊列話題的文章,其中有一句提到
「由於兩個操做提交的時間間隔很近,線程池中的線程,誰先啓動是不定的。」
瞬間以爲這個queue名字有點忽悠人了,還不如pool~
綜合一點,咱們知道他能夠比較大的用處在於能夠幫組多線程編程就行了。
51.What is lazy loading?
答案:懶漢模式,只在用到的時候纔去初始化。
也能夠理解成延時加載。
我以爲最好也最簡單的一個列子就是tableView中圖片的加載顯示了。
一個延時載,避免內存太高,一個異步加載,避免線程堵塞。
52.Can we use two tableview controllers on one viewcontroller?
是否在一個視圖控制器中嵌入兩個tableview控制器?
答案:一個視圖控制只提供了一個View視圖,理論上一個tableViewController也不能放吧,
只能說能夠嵌入一個tableview視圖。固然,題目自己也有歧義,若是不是咱們定性思惟認爲的UIViewController,
而是宏觀的表示視圖控制者,那咱們卻是能夠把其當作一個視圖控制者,它能夠控制多個視圖控制器,好比TabbarController
那樣的感受。
53.Can we use one tableview with two different datasources? How you will achieve this?
一個tableView是否能夠關聯兩個不一樣的數據源?你會怎麼處理?
答案:首先咱們從代碼來看,數據源如何關聯上的,實際上是在數據源關聯的代理方法裏實現的。
所以咱們並不關心如何去關聯他,他怎麼關聯上,方法只是讓我返回根據本身的須要去設置如相關的數據源。
所以,我以爲能夠設置多個數據源啊,可是有個問題是,你這是想幹嗎呢?想讓列表如何顯示,不一樣的數據源分區塊顯示?