1.項目經驗
2.基礎問題
3.指南認識
4.解決思路
ios開發三大塊:
1.Oc基礎
2.CocoaTouch框架
3.Xcode使用
--------------------
CocoaTouch
Media
Core Services
Core OS
--------------------
System Framework
OC的類聲明,定義域
OC關鍵字定義為 @class
O-C特有的語句for(。。in 。。)迭代循環,其他的條件和循環語句和c一樣
OC對面向對象的概述
(1)基類:NSOject
(2)一般的繼承是單繼承,使用協議@protocol 實現多重繼承
(3)所有的函數都是虛函數
Id類型
OC中每個目標都可以表達為id類型,泛型。可以認為是NSObject *或者 void Nil
等同於null,表示一個目標指針
類定義
Oc的類分為2個文件,
.h文件存放類,函數的聲明(聲明的關鍵字 @interfance @end)
.m文件存放類的具體實現(實現關鍵字)
對象和類的方法
“+” 表示類的方法
“-”表示對象的方法 -(int)返回值f 函數的名字: (int) x;參數(有個“:”表示有幾個參數,從第二個參數起“:”前面必須加空格)
對於方法聲明的講解
“:”表示繼承 @interface Dog : NSObject{} @end
“{}”之間只能寫字段(如:int age),不能寫函數
右括號和@end間接寫的是函數
創建對象
Dog *dog=[Dog alloc] ; 一個類的名字 + alloc
初始化構造函數
[dog init]; 凡是以init…開頭的都是構造函數
銷毀對象
[dog release];
字段定義
三種作用域:@public @protected(保護,在類本身或者子類中) @private (只能在類的內部)
補充:缺省的是protected
函數全部用public
變量必須定義在類{}之間的地方
注:在c中函數和字段是可以重名的
類的聲明
必須帶“*” 即表示指針也表示引用 Dog(對象) * myDog (變量名)
訪問 myDog.dog(變量名訪問字段)或者使用空格
多參數方法
帶兩個參數(函數名為f::)
兩種寫法 -(float)f(int)x 【空格】 :(int)y 不提倡這種寫法
(2)-(float)f(int)x 【空格】g:(int)y g:表示標簽 (第一參數不能有標簽,第一個函數名就相當於第一個參數的標簽,是為了方便閱讀)
如何調用方法
無參數
-(int)foo;
Int ret=[obj foo] 調obj的方法,沒有參數,調方法的時候用[]
一個參數
-(int)foo:(int)a;
Int ret=[obj foo:10]
帶標簽
-(int)foo:(int)a andB(int)b;
Int ret=[obj foo:10 andB:2];
OC不是嚴格的函數重載
-(int)g:(int)x;
-(int)g:(folat)x;兩個函數的函數名都為”g:” 在OC中是錯誤的,但是c中是可行
函數作用域聲明
.h中定義的所有函數都是public類型的
私有化的解決方法
在.m文件中使用Categories
@property age
合成定義在.h文件中使用 編譯器
=(1)”-(void)setAge:(int)newAge;” + “-(int) age;”
@synthesize 合成實現,編譯器自動實現getter和setter函數
=(1)”-(void)setAge:(int)newAge{ age = newAge;}”+”return age;”
屬性可以是
readwrite(缺省),readonl:
表示可讀寫(setter和getter函數都可以使用),readonly只能用getter
assign(缺省)、retain,copy
表示屬性如何存儲 assign相當於“=”表示賦值
Nonatomic(UI中常用)
表示不用考慮線程安全問題
getter=…,setter=…
重新設置getter函數和setter函數名
點語法
內部類age和點age(.age)不同
直接訪問age相當於訪問age字段,
.age在等號左邊相當於setter函數,在等號的右邊相當於getter函數
例子:dog.age=200;展開成[dog setAge:200];
說明:
(1)age不是變量的名字,而是函數
(2)點語法在等號的左邊表示設置函數(set…)
dogAge = dog.age;展開成 dogAge = [dog age]; (系統自動展開)
@class 與 #import :
import會包含這個類的所有信息,包括實體變量和方法,
而@class只是告訴編譯器,其后面聲明的名稱是類的名稱
在頭文件中, 一般只需要知道被引用的類的名稱就可以了。 不需要知道其內部的實體變量和方法,
所以在頭文件中一般使用@class來聲明這個名稱是類的名稱。
而在實現類里面,因為會用到這個引用類的內部的實體變量和方法,
所以需要使用#import來包含這個被引用類的頭文件。
在編譯效率方面考慮,如果你有100個頭文件都#import了同一個頭文件,或者這些文件是依次引用的,
如A–>B, B–>C, C–>D這樣的引用關系。當最開始的那個頭文件有變化的話,后面所有引用它的類都需要重新編譯,
如果你的類有很多的話,這將耗費大量的時間。而是用@class則不會。
如果有循環依賴關系,如:A–>B, B–>A這樣的相互依賴關系,如果使用#import來相互包含,那么就會出現編譯錯誤,
如果使用@class在兩個類的頭文件中相互聲明,則不會有編譯錯誤出現。
所以,一般來說,@class是放在interface中的,只是為了在interface中引用這個類,把這個類作為一個類型來用的。
在實現這個接口的實現類中,如果需要引用這個類的實體變量或者方法之類的,還是需要import在@class中聲明的類進來.
字符串
NSString: Cocoa中處理字符串的類
NSString型數據是特殊的NSString字面量,其指示標志是雙引號內的字符串前的@,如@“Hi!”
NSString的stringWithFormat:方法就是通過格式字符串和參數來創建NSString的
+(id)stringWithFormat:(NSString *)format,...;
例子:
NSString *height;
Height=[NSString stringWithFormat:@”Your height is %d feet,%d inches”,5,11];
stringWithForat:(1)定義最后的省略號:可以接受對個以逗號隔開的其他參數
(2)“+”修飾的方法,為類方法,這個方法屬於類對象(而不是類的實例對象)並且通常用於創建新的實例
是一個工廠方法,根據提供的參數創建新對象
“-”創建的大部分方法都是實例方法
NSString的實例方法length。返回的是字符串中的字符個數
使用 -(unsigned int)length:
Unsigned int length=[height length];
If([height length]>35){
NSLog(@”wow,you’re relly tall!”)}
比較字符串
isEqualToString:可以用來比較接收方和當做參數傳遞來的字符串。返回一個BOOL型數據表示字符串的內容是否相同,
-(BOOL)isEqualToString:(NSString *)aString;
具體的使用方法:
NSString *thing1=@“hello 5”;
NSString *thing2;
Thing2=[NSString stringWithFormat:@“hello %d”,5];
If([thing1 isEqualToString:thing2]){ NSLog(@”They are the same!);
注意:“==“運算符只判斷thing1和thing2的這真數值,而不是他們所指的對象
兩個字符串是否相等(等價性,兩個字符串是否代表同一個事物)用isEqualToString
Compare:(區分大小寫的比較的字符逐個字符的進行比較,,返回一個NSComparisonResult(就是一個enum型數據)來顯示比較結果。如返回值是NSOrderedAscending,那么左側的數值就小右側的數值,即compare的目標在字母表中的排序位置比傳遞進來的字符串更靠前
Compare:options:
例子:-(NScomparisonResult)compare:(NSString *)string
options:(unsigned)mask;
options參數是一個位掩碼。可以使用位或(bitiwise-OR)運算符(|)來添加選項標記。常用的選項如下:
NSCaseInsensitiveSearch:不區分大小寫字符
NSLiteralSearch:進行完全比較,區分大小寫
NSNumericSearch:比較字符串的字符個數,而不是字符值,
可變數組
與NSString一樣NSArray創建的是不可變對象的數組。補充類NSMutableArray,可以隨意的田間和刪除數組,通過類方法arrayWithCapacity來創建新的可變數組
+(id)arrayWithCapacity:(unsignde)numltems
刪除特定索引處德對象。removeObject
枚舉
NSEnumerator是Cocoa用來描述集合迭代運算的方式,需通過objectEnumerator像組組請求枚舉器
-(NSEnumerator *)objcetEnumerator
從后向前瀏覽集合 reverseObjectEnumerator
可以用while循環,每次循環都向枚舉器請求他的nextObject(下一個對象)
-(id)nextObject;返回nil時,循環結束
注:不能通過添加或刪除對象這類方式來改變
字典:NSDictionary(也成為散列表或關聯類表)使用的是鍵查詢的優化存儲方式
就是關鍵字及其定義的集合
NSDictionary在給定的關鍵字(通常是一個NSString字符串)下存儲一個數值(可以是任何類型的對象
與NSString和NSArray一樣只能使用NSMutableDictionary添加或者刪除
創建字典dictionaryWithObjectsAndKeys;
+(id)dictionaryWithObjectsAndKeys:
(id)firstObject,…;
objectForKey:獲取字典中得值,向方法傳遞之前用來存儲改制的關鍵字
-(id)objectForKey:(id)aKey;
添加元素
-(void)setObject:forkey
NSNumber類來包裝(即以對象形式實現)基本數據類型:
創建NSNumber對象:
+(NSNumber *)numberWithChar:(char) value;
+(NSNumber *)numberWithint:(int)value;
+(NSNumber *)numberWithFolatr (float) value;
+(NSNumber *)numberWithBOOL (BOOL) value;
對初學者來說,Objective-C存在了很多令人費解的寫法,實際上他們是非常優雅的。
程序員寫的最多的就是函數以及調用自己寫的或者別人寫的函數。本文就從函數的角度來看下Objective-C的優雅之處。
C#和Objective-C同屬於c系列語言。讓我們先看下C#的函數定義和調用,做個對比。
C#函數的定義:
- public void doIt(string actorName, string movieName, int timesSeen)
- {
- Console.Write("{0} is my favorite actor in the movie {1}, I saw it {2} times.", actorName, movieName, timesSeen);
- }
函數的調用:
- Class1 objMovie = new Class1();
- objMovie.doIt("萊昂納多·迪卡普里奧", "盜夢空間", 120);
在讓.net程序員看下Objective-C的定義:
- - (void) doIt:(NSString *) actorName movieName: (NSString*) value timesSeen: (int)times {
- NSLog(@"%@ is my favorite actor in the movie %@, I saw it %i times.",actorName, value, times);
- }
如果你第一次看Objective-C,肯定會琢磨不透上面的代碼,懷疑是不是寫錯了。
對於上面這個函數的定義:
1、'-'表示這個函數是實例函數(類似非靜態函數),'+'表示這個函數是類函數(類似靜態函數)
2、(void)表示這個函數沒有返回值。
3、函數名是'doIt:',而不是'doIt'
4、參數用空格隔開
5、參數類型寫在括號中
6、參數分內部參數和外部參數,如電影名稱,內部參數是:value,外部參數是:movieName
7、函數的一個參數沒有外部參數的名稱,有內部參數名。如:actorName。
調用:
從上面代碼可以看出除了第一個參數,其余的參數都可以加上外部參數名稱用於區別。
從上面可以看出Objective-C和C#區別很大,實在會令.net程序員費解。Objective-C函數設計的優雅之處在於即有內部參數名又有外部參數名,可以不用在再內部定義變量來存放函數的參數。
對Objective-C函數學習的一個簡單總結。
- 運行過程
1.編寫OC程序:.m源文件
2.編譯.m文件為.o目標文件:cc -c xxxx.m
3.鏈接.o文件為a.out可執行文件:cc xxxx.o -framework Foundation
4.執行a.out文件:./a.out
- #import 的功能跟#include一樣,只是更好用,他避免了頭文件的多次包含
- 為了能使用OC的特性, 一定要引入#import <Foundation/Foundation.h>
-
類定義// @implementation 和 @end
// 設計(定義)一個車類 // @implementation 和 @end // : NSObject :讓Car這個類具備創建對象的能力(繼承) @implementation Car : NSObject // 這個大括號里面只能寫所有的屬性 { // @public:讓對象的屬性可以被外面的指針訪問,默認是私有的 @public int wheels; // 默認基本數據類型的初始值都是0 } // 在@end的前面,大括號{}外面寫行為 // 給Car對象增加一個行為(方法) // 給對象增加一個行為,必須以減號 - 開頭, 給類增加一個對象是+。 // OC方法中的小括號()只是主要擴住類型 - (void) run { // 訪問車子對象內部的屬性,直接用屬性名就可以 NSLog(@"%i個輪子,%f時速的車子跑起來了!", wheels, speed); } + (Void) test { // 這是類方法。上面那個-號的是對象方法。 } @end
- 類調用
// 在OC中想執行一些行為,首先寫個 [行為執行者 行為名稱] // new這個行為執行完畢后,會返回這個對象的地址 Car *c = [Car new]; // 給c指向的車子對象的wheels屬性賦值 c->wheels = 4; // 等價於 (*c).wheels = 4 // 給指針變量c指向的對象“發送”一條run消息,讓這個對象執行run這個行為 [c run];
- 聲明&實現
// 聲明一個類 /* 1.類名 2.繼承了NSObject 3.聲明屬性 4.聲明方法(僅僅是聲明,不需要實現) 5.實現和聲明中的成員變量不能同名 */ @interface Book : NSObject { @public double price;// 這些屬性稱為對象的“成員變量” } // 聲明一個方法(行為) - (void)reng; @end
// 定義(實現)一個類 /* 只用來實現@interface中聲明的方法 */ @implementation Book - (void)reng { NSLog(@"%f的書被扔了!", price); }
- 多參數的聲明和使用
- (void) fly { NSLog(@"i can fly, my age is %d", age); } // 一個參數對應一個冒號 // 冒號也是方法名的一部分 - (void)fly:(int)howHeight { NSLog(@"i can fly, my age is %d, my height %d", age, howHeight); } // 多個參數的情況。 withTime是方法名的一部分.times是參數名稱 - (void)fly:(int)howHeight :WithTime(int)times { }
Person *p = [Person new]; [p fly]; [p fly:99]; [p fly:99 WithTime:10];
- OC對象方法和函數的區別
1. 函數屬於整個文件,在文件的任意地方都能調用;對象的方法只屬於這個對象,只有對象才能調用
2. 對象的方法只能聲明在@infterface 和@end 之間,對象方法只能實現在@implementation 和@end之間。
函數的聲明和定義可以寫在任意地方,函數不能歸某個類所有,只屬於某個文件。
- 消息機制
給指針變量所指向的對象發送一條消息(消息名稱就是方法名),讓那個對象執行相應的方法(動態)
iOS求職之OC面試題
1、Objective-C的類可以多重繼承么?可以采用多個協議么?
答:不可以多重繼承,可以采用多個協議。
2、#import和#include的區別是什么?#import<> 跟 #import""有什么區別?
#import能避免頭文件被重復包含的問題:
1) 一般來說,導入objective c的頭文件時用#import,包含c/c++頭文件時用#include。
使用include要注意重復引用的問題:
class A,class B都引用了class C,class D若引用class A與class B,就會報重復引用的錯誤。
2)#import 確定一個文件只能被導入一次,這使你在遞歸包含中不會出現問題。
所以,#import比起#include的好處就是它避免了重復引用的問題。所以在OC中我們基本用的都是import。
#import<> 包含iOS框架類庫里的類,#import""包含項目里自定義的類。
3、Category是什么?擴展一個類的方式用繼承好還是類目好?為什么?
答:Category是類目。用類目好,因為繼承要滿足a is a b的關系,而類目只需要滿足a has a b的關系,局限性更小,你不用定義子類就能擴展一個類的功能,還能將類的定義分開放在不同的源文件里, 用Category去重寫類的方法,僅對本Category有效,不會影響到其他類與原有類的關系。
4、延展是什么?作用是什么?
答:延展(extension):在自己類的實現文件中添加類目來聲明私有方法。
5、類實例(成員)變量的@protected,@private,@public聲明各有什么含義?
@protected:受保護的,該實例變量只能在該類和其子類內訪問,其他類內不能訪問。
@private:私有的,該實例變量只能在該類內訪問,其他類內不能訪問。
@public:共有的,該實例變量誰都可以訪問。
6、id聲明的對象有什么特性?
Ø 沒有 * 號
Ø 動態數據類型
Ø 可以指向任何類的對象(設置是nil),而不關心其具體類型
Ø 在運行時檢查其具體類型
Ø 可以對其發送任何(存在的)消息
7、委托是什么?委托和委托方雙方的property聲明用什么屬性?為什么?
委托:一個對象保存另外一個對象的引用,被引用的對象實現了事先確定的協議,該協議用於將引用對象中的變化通知給被引用對象。
委托和委托方雙方的property聲明屬性都是assign而不是retain
為了避免循環引用造成的內存泄露。
循環引用的問題這樣理解:
比如在main函數中創建了兩個類的對象A和B,現在引用計數都是1。現在讓A和B互相引用(A有一個屬性是B對象,屬性說明是retain;B有一個屬性是A對象,屬性說明是retain),現在兩個對象的引用計數都增加了1,都變成了2。
現在執行[A release]; [B release]; 此時創建對象的main函數已經釋放了自己對對象的所有權,但是此時A和B的引用計數都還是1,因為他們互相引用了。
這時你發現A和B將無法釋放,因為要想釋放A必須先釋放B,在B的dealloc方法中再釋放A。同理,要想釋放B必須先釋放A,在A的dealloc方法中再釋放B。所以這兩個對象將一直存在在內存中而不釋放。這就是所謂的循環引用的問題。要想解決這個問題,一般的方法可以將引用的屬性設置為assign,而不是retain來處理。
8、淺拷貝和深拷貝區別是什么?
淺層復制:只復制指向對象的指針,而不復制引用對象本身。
深層復制:復制引用對象本身。
意思就是說我有個A對象,復制一份后得到A_copy對象后,對於淺復制來說,A和A_copy指向的是同一個內存資源,復制的只不過是是一個指針,對象本身資源還是只有一份,那如果我們對A_copy執行了修改操作,那么發現A引用的對象同樣被修改,這其實違背了我們復制拷貝的一個思想。深復制就好理解了,內存中存在了兩份獨立對象本身。
用網上一哥們通俗的話將就是:
淺復制好比你和你的影子,你完蛋,你的影子也完蛋
深復制好比你和你的克隆人,你完蛋,你的克隆人還活着。
9、內存管理的幾條原則是什么?按照默認法則,哪些關鍵字生成的對象需要手動釋放?哪些情況下不需要手動釋放,會直接進入自動釋放池?
• 當使用new、alloc或copy方法創建一個對象時,該對象引用計數器為1。如果不需要使用該對象,可以向其發送release或autorelease消息,在其使用完畢時被銷毀。
• 如果通過其他方法獲取一個對象,則可以假設這個對象引用計數為1,並且被設置為autorelease,不需要對該對象進行清理,如果確實需要retain這個對象,則需要使用完畢后release。
• 如果retain了某個對象,需要release或autorelease該對象,保持retain方法和release方法使用次數相等。
使用new、alloc、copy關鍵字生成的對象和retain了的對象需要手動釋放。設置為autorelease的對象不需要手動釋放,會直接進入自動釋放池。
10、怎樣實現一個單例模式的類,給出思路,不寫代碼。
• 首先必須創建一個全局實例,通常存放在一個全局變量中,此全局變量設置為nil
• 提供工廠方法對該全局實例進行訪問,檢查該變量是否為nil,如果nil就創建一個新的實例,最后返回全局實例
• 全局變量的初始化在第一次調用工廠方法時會在+allocWithZone:中進行,所以需要重寫該方法,防止通過標准的alloc方式創建新的實例
• 為了防止通過copy方法得到新的實例,需要實現-copyWithZone方法
• 只需在此方法中返回本身對象即可,引用計數也不需要進行改變,因為單例模式下的對象是不允許銷毀的,所以也就不用保留
• 因為全局實例不允許釋放,所以retain,release,autorelease方法均需重寫
11、@class的作用是什么?
答:在頭文件中, 一般只需要知道被引用的類的名稱就可以了。 不需要知道其內部的實體變量和方法,所以在頭文件中一般使用@class來聲明這個名稱是類的名稱。 而在實現類里面,因為會用到這個引用類的內部的實體變量和方法,所以需要使用#import來包含這個被引用類的頭文件。
• @class的作用是告訴編譯器,有這么一個類,用吧,沒有問題
• @class還可以解決循環依賴的問題,例如A.h導入了B.h,而B.h導入了A.h,每一個頭文件的編譯都要讓對象先編譯成功才行
• 使用@class就可以避免這種情況的發生
12、KVC是什么?KVO是什么?有什么特點?
• KVC是鍵值編碼,特點是通過指定表示要訪問的屬性名字的字符串標識符,可以進行類的屬性讀取和設置
• KVO是鍵值觀察,特點是利用鍵值觀察可以注冊成為一個對象的觀察者,在該對象的某個屬性變化時收到通知
13、MVC是什么?有什么特性?
– MVC是一種設計模式,由模型、視圖、控制器3部分組成。
– 模型:保存應用程序數據的類,處理業務邏輯的類
– 視圖:窗口,控件和其他用戶能看到的並且能交互的元素
– 控制器:將模型和試圖綁定在一起,確定如何處理用戶輸入的類
14、定義屬性時,什么情況使用copy、assign、retain?
使用assign: 對基礎數據類型 (NSInteger,CGFloat)和C數據類型(int, float,double, char, 等等)
使用copy: 希望獲得源對象的副本而不改變源對象內容時,對NSString
使用retain: 希望獲得源對象的所有權時,對其他NSObject和其子類
15.屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那種情況下用?
assign用於簡單數據類型,如NSInteger,double,bool,
retain和copy用於對象,
readwrite是可讀可寫特性;需要生成getter方法和setter方法時
readonly是只讀特性 只會生成getter方法 不會生成setter方法 ;不希望屬性在類外改變
assign是賦值特性,setter方法將傳入參數賦值給實例變量;僅設置變量時;
retain表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的retaincount會+1;
copy表示賦值特性,setter方法將傳入對象復制一份;需要完全一份新的變量時。
nonatomic非原子操作,決定編譯器生成的setter getter是否是原子操作,atomic表示多線程安全,一般使用nonatomic
16.id 聲明的對象有什么特性?
答:Id聲明的對象具有運行時的特性,即可以指向任意類型的objcetive-c的對象;
17.Objective-C如何對內存管理的,說說你的看法和解決方法?
答:Objective-C的內存管理主要有三種方式ARC(自動內存計數)、手動內存計數、內存池。
18.內存管理的幾條原則時什么?
誰申請,誰釋放
遵循Cocoa Touch的使用原則;
內存管理主要要避免“過早釋放”和“內存泄漏”,對於“過早釋放”需要注意@property設置特性時,一定要用對特性關鍵字,對於“內存泄漏”,一定要申請了要負責釋放,要細心。
19.那些關鍵字生成的對象 需要手動釋放?
答:關鍵字alloc 或new 生成的對象需要手動釋放
20在和property結合的時候怎樣有效的避免內存泄露?
答:設置正確的property屬性,對於retain需要在合適的地方釋放
21.如何對iOS設備進行性能測試?
Profile-> Instruments ->Time Profiler
22.Object-c的類可以多重繼承么?可以實現多個接口么?
答:Object-c的類不可以多重繼承;可以實現多個接口,通過實現多個接口可以完成C++的多重繼承;
23.Category是什么?重寫一個類的方式用繼承好還是分類好?為什么?
答:Category是類別,一般情況用分類好,用Category去重寫類的方法,僅對本Category有效,不會影響到其他類與原有類的關系。
24.描述一下iOS SDK中如何實現MVC的開發模式
MVC是模型、試圖、控制開發模式,對於iOS SDK,所有的View都是視圖層的,它應該獨立於模型層,由視圖控制層來控制。所有的用戶數據都是模型層,它應該獨立於視圖。所有的ViewController都是控制層,由它負責控制視圖,訪問模型數據
25. Object C中創建線程的方法是什么?如果在主線程中執行代碼,方法是什么?如果想延時執行代碼、方法又是什么?
線程創建有三種方法:使用NSThread創建、使用 GCD的dispatch、使用子類化的NSOperation,然后將其加入NSOperationQueue;在主線程執行代碼,方法是 performSelectorOnMainThread,如果想延時執行代碼可以用performSelector:onThread:withObject:waitUntilDone
26、iPhone5 的屏幕分辨率大小為 1136* 640 ?
答:屏幕分辨率:用於量度位圖圖像內數據量多少的一個參數。通常表示成ppi(每英寸像素Pixel per inch)。屏幕物理尺寸不變,分辨率越高,每單位面積內包含的細節(像素點)越多。
27、struct strA { int a; float b; char c; } expA;
printf("%ld",sizeof(expA)); 輸出結果為 12 ?
該問題涉及編譯器的“內存對齊”問題:
現代計算機中內存空間都是按照byte(字節)划分的,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定變量的時候經常在特定的內存地址訪問,這就需要各類型數據按照一定的規則在空間上排列,而不是順序的一個接一個的排放,這就是對齊。
對齊的作用和原因:各個硬件平台對存儲空間的處理上有很大的不同。一些平台對某些特定類型的數據只能從某些特定地址開始存取。其他平台可能沒有這種情況, 但是最常見的是如果不按照適合其平台的要求對數據存放進行對齊,會在存取效率上帶來損失。比如有些平台每次讀都是從偶地址開始,如果一個int型(假設為 32位)如果存放在偶地址開始的地方,那么一個讀周期就可以讀出,而如果存放在奇地址開始的地方,就可能會需要2個讀周期,並對兩次讀出的結果的高低 字節進行拼湊才能得到該int數據。顯然在讀取效率上下降很多。這也是空間和時間的博弈。
通常,我們寫程序的時候,不需要考慮對齊問題。編譯器會替我們選擇適合目標平台的對齊策略。當然,我們也可以通知給編譯器傳遞預編譯指令而改變對指定數據的對齊方法。
但是,正因為我們一般不需要關心這個問題,所以因為編輯器對數據存放做了對齊,而我們不了解的話,常常會對一些問題感到迷惑。最常見的就是struct數據結構的sizeof結果,出乎意料。
對於結構體來說,按成員中所占字節最大的是float類型,占用4個字節,一共有3個成員,所以總的占用字節為:4* 3 = 12.
可通過編譯器命令來設定:
#progma pack (2)
28、@property語法中readonly/readwrite,atomic/nonatomic的作用,@dynamic的作用?
@Property:Objective-C語言關鍵詞,與@synthesize配對使用。xcode4.5以及以后的版本,@synthesize可以省略。
功能:讓編譯器自動編寫一對與數據成員同名的方法聲明來省去讀寫方法的聲明。
聲明property的語法為:
@property (參數1,參數2) 類型 名字;
如:@property(nonatomic,retain) UIWindow *window;
其中參數主要分為三類:
讀寫屬性: (readwrite/readonly)
setter語意:(assign/retain/copy)
原子性: (atomicity/nonatomic)
各參數意義如下:
readwrite:同時產生setter\getter方法
readonly:只產生簡單的getter,沒有setter。
assign:默認類型,setter方法直接賦值,而不進行retain操作
retain:setter方法對參數進行release舊值,再retain新值。
copy:setter方法進行Copy操作,與retain一樣
atomic:原子性,它沒有一個如果你沒有對原子性進行一個聲明(atomic or nonatomic),那么系統會默認你選擇的是atomic。
原子性就是說一個操作不可以被中途cpu暫停然后調度, 即不能被中斷, 要不就執行完, 要不就不執行. 如果一個操作是原子性的,那么在多線程環境下, 就不會出現變量被修改等奇怪的問題。原子操作就是不可再分的操作,在多線程程序中原子操作是一個非常重要的概念,它常常用來實現一些同步機制,同時也是一些常見的多線程Bug的源頭。當然,原子性的變量在執行效率上要低些。
關於異步與同步:並非同步就是不好,我們通常需要同時進行多個操作,這時使用異步,而對於程序來說,一般就是使用多線程,然而我們很多時候需要在多個線程間訪問共享的數據,這個時候又需要同步來保證數據的准確性或訪問的先后次序。當有多個線程需要訪問到同一個數據時,OC中,我們可以使用@synchronized(變量)來對該變量進行加鎖(加鎖的目的常常是為了同步或保證原子操作)。
nonatomic:非原子性,是直接從內存中取數值,因為它是從內存中取得數據,它並沒有一個加鎖的保護來用於cpu中的寄存器計算Value,它只是單純的從內存地址中,當前的內存存儲的數據結果來進行使用。在多線環境下可提高性能,但無法保證數據同步。
29、OSI(Open System Interconnection)開放式系統互聯參考模型 把網絡協議從邏輯上分為了7層,試列舉常見的應用層協議。
注意問的是應用層協議,有些同學直接答了七層模型。
在開放系統互連(OSI)模型中的最高層,為應用程序提供服務以保證通信,但不是進行通信的應用程序本身。
Telnet協議是TCP/IP協議族中的一員,是Internet遠程登陸服務的標准協議和主要方式。它為用戶提供了在本地計算機上完成遠程主機工作的能力。
FTP文件傳輸協議是TCP/IP網絡上兩台計算機傳送文件的協議,FTP是在TCP/IP網絡和INTERNET上最早使用的協議之一,它屬於網絡協議組的應用層。
超文本傳輸協議 (HTTP-Hypertext transfer protocol) 是分布式,協作式,超媒體系統應用之間的通信協議。是萬維網(world wide web)交換信息的基礎。
SMTP(Simple MailTransfer Protocol)即簡單郵件傳輸協議,它是一組用於由源地址到目的地址傳送郵件的規則,由它來控制信件的中轉方式,它幫助每台計算機在發送或中轉信件時找到下一個目的地。
時間協議(TIME protocol)是一個在RFC 868內定義的網絡協議。它用作提供機器可讀的日期時間資訊。
DNS 是域名系統 (Domain NameSystem) 的縮寫,是因特網的一項核心服務,它作為可以將域名和IP地址相互映射的一個分布式數據庫。
SNMP(Simple Network ManagementProtocol,簡單網絡管理協議)的前身是簡單網關監控協議(SGMP),用來對通信線路進行管理。
TFTP(Trivial FileTransfer Protocol,簡單文件傳輸協議)是TCP/IP協議族中的一個用來在客戶機與服務器之間進行簡單文件傳輸的協議,提供不復雜、開銷不大的文件傳輸服務。端口號為69。
30、網絡傳輸層協議中,基於TCP/IP協議和UDP/IP的連接有什么區別?
TCP:TransmissionControl Protocol 傳輸控制協議TCP是一種面向連接(連接導向)的、可靠的、基於字節流的運輸層(Transport layer)通信協議,由IETF的RFC 793說明(specified)。
UDP 是User DatagramProtocol的簡稱, 中文名是用戶數據包協議,是OSI 參考模型中一種無連接的傳輸層協議,提供面向事務的簡單不可靠信息傳送服務,IETF RFC 768是UDP的正式規范。
面向連接:是指通信雙方在通信時,要事先建立一條通信線路,其有三個過程:建立連接、使用連接和釋放連接。電話系統是一個面向連接的模式,撥號、通話、掛機;TCP協議就是一種面向連接的協議。
面向無連接:是指通信雙方不需要事先建立一條通信線路,而是把每個帶有目的地址的包(報文分組)送到線路上,由系統自主選定路線進行傳輸。郵政系統是一個無連接的模式,天羅地網式的選擇路線,天女散花式的傳播形式;IP、UDP協議就是一種無連接協議。
31、簡述MVC模式中M、V、C分別指代什么及發揮的作用?
MVC開始是存在於Desktop(桌面)程序中的,M是指數據模型,V是指用戶界面,C則是控制器,使用MVC的目的是將M和V的實現代碼分離。C存在的目的則是確保M和V的同步,一旦M改變,V應該同步更新。
視圖是用戶看到並與之交互的界面,視圖沒有真正的處理發生,不管這些數據是聯機存儲的還是一個雇員列表,作為視圖來講,它只是作為一種輸出數據並允許用戶操縱的方式。
模型表示企業數據和業務規則,模型返回的數據是中立的,就是說模型與數據格式無關,這樣一個模型能為多個視圖提供數據,由於應用於模型的代碼只需寫一次就可以被多個視圖重用,所以減少了代碼的重復性。
控制器接受用戶的輸入並調用模型和視圖去完成用戶的需求,控制器本身不輸出任何東西和做任何處理。它只是接收請求並決定調用哪個模型構件去處理請求,然后再確定用哪個視圖來顯示返回的數據。
32、聲明@property的語法中,retain、copy、assign的含義及作用?試寫出 @property中帶retain和assign關鍵字,通過@synthesize自動生成的的合成存取方法(set、get方法)的實現代碼。
getter分析:
@property (nonatomic, retain) test*aTest;
@property (nonatomic, copy) test*aTest;
等效代碼:
-(void)aTest {
return aTest;
}
========== 貌似我是分割線 ===========
@property (retain) test* aTest;
@property (copy) test* aTest;
等效代碼:
-(void)aTest
{
[aTest retain];
return [aTest autorelease];
}
setter分析:
@property (nonatomic, retain) test*aTest;
@property (retain) test* aTest;
等效於:
-(void)setaTest:(test *)newaTest {
if (aTest !=newaTest) {
[aTest release];
aTest = [newaTest retain];
}
}
========== 貌似我是分割線 ===========
@property (nonatomic, copy) test*aTest;
@property (copy) test* aTest;
等效於:
-(void)setaTest:(test *)newaTest {
if (aTest != newaTest){
[aTest release];
aTest = [newaTest copy];
}
}
33、iOS中有哪些回調機制,並作簡單的比較。
各種回調機制的比較:
1)目標動作對:當兩個對象之間有比較緊密的關系時,如視圖控制器與其下的某個視圖。
2)代理:也叫委托,當某個對象收到多個事件,並要求同一個對象來處理所有事件時。委托機制依賴於某個協議定義的方法來發送消息。
3)通告機制:當需要多個對象或兩個無關對象處理同一個事件時。
4)Block:適用於回調只發生一次的簡單任務。
34、列出在編碼中哪些編碼習慣有助於提高代碼質量、軟件性能和健壯性,減少程序崩潰。
#使用嚴格的命名規則(如匈牙利命名法)能夠避免不必要的類型轉換錯誤。
#在編碼前先設計好流程圖或使用偽代碼,清晰化整個設計意圖。
#對自己的代碼進行嚴格的單元測試(unit testing)。
單元測試是指對軟件中的最小可測試單元進行檢查和驗證。如C語言中單元指一個函數,Java里單元指一個類,圖形化的軟件中可以指一個窗口或一個菜單等。總的來說,單元就是人為規定的最小的被測功能模塊。單元測試是在軟件開發過程中要進行的最低級別的測試活動,軟件的獨立單元將在與程序的其他部分相隔離的情況下進行測試。
#異常的處理
首先不要輕易使用異常的捕獲,其次要盡可能捕獲具體的異常。對於異常的處理最好能夠采用封裝的方式,大家統一使用。這樣可以保證異常處理的一致性也可以保證當異常出現時性能的穩定。
# 使用內省的方法檢查方法的輸入
#采用增量式的編程方式。
采用增量式編程和測試,會傾向於創建更小的方法和更具內聚性的類。你應該經常評估代碼質量,並不時的進行許多小調整,而不是一次修改許多東西。在寫了幾行代碼之后,就應該進行一次構建/測試。在沒有得到反饋時,你不要走的太遠。
#使用工具(如Instrument)來幫助檢查內存泄漏、過早釋放內存、CPU使用效率等問題。
#消除所有的編譯警告,警告就是錯誤。
#寫防御性的代碼,使用內省的方法檢查傳入的參數。
35、JSON中{ }代表_____,[ ]代表_____,試將下面的JSON串用OC對象表示出來:
{ "people": [
{ "firstName": "Brett","lastName":"McLaughlin", "email":"aaaa" },
{ "firstName": "Jason","lastName":"Hunter", "email": "bbbb"},
{ "firstName": "Elliotte","lastName":"Harold", "email": "cccc" }
],
“location”:”中華人民共和國”
}
JSON中{ }代表對象,數據結構為{key1:value1, key2:value2, key3:…… }
[ ]代表數組,與其他語言中的數組類似。
//
@interface People: NSObject
@property(nonatomic, copy) NSString* strFirstName;
@property(nonatomic, copy) NSString* strLastName;
@property(nonatomic, copy) NSString* strEmail;
@end
//
@interfaceJSonData : NSObject
@property(nonatomic, retain) NSMutableArray* arrPeople; // 存放People對象
@property(nonatomic, copy) NSString* strLocation;
@end
36. Object-C有多繼承嗎?沒有的話用什么代替?
答:沒有,cocoa 中所有的類都是NSObject 的子類,多繼承在這里是用protocol 委托代理來實現的 ,ood的多態特性在obj-c中通過委托來實現。
37.bject-C有私有方法嗎?私有變量呢?
objective-c – 類里面的方法只有兩種, 靜態方法和實例方法.
在類里面聲名一個私有方法 @interface Controller : NSObject
{ NSString *something;
} + (void)thisIsAStaticMethod; –(void)thisIsAnInstanceMethod; @end @interface Controller
(private)
-(void)thisIsAPrivateMethod; @end
@private可以用來修飾私有變量 在Objective‐C中,所有實例變量默認都是私有的,所有實例方法默認都是公有的
38. 堆和棧的區別?
管理方式:對於棧來講,是由編譯器自動管理,無需我們手工控制;對於堆來說,釋放工作由程序員控制,容易產生memory leak。
申請大小:棧:棧是向低地址擴展的數據結構,是一塊連續的內存的區域
堆:是向高地址擴展的數據結構,是不連續的內存區域。
分配方式:堆都是動態分配的 ,動態分配由alloca函數進行分配
棧的動態分配由編譯器進行釋放,無需我們手工實現
39. kvc和kvo的區別?
kvc:鍵值編碼,是一種間接訪問對象的屬性,使用字符串來標示屬性
kvo:鍵值觀察機制,提供了觀察某一屬性變化的方法
40. 線程和進程的區別?
答:主要不同的是操作系統資源管理方式
線程是一個進程中不同的執行路徑,線程有自己的堆、局部變量
進程有獨立的地址空間,一個線程死掉,整個進程就會死掉
41. #import和#include的區別,@class代表什么?
答:@class一般用於頭文件中需要聲明該類的某個實例變量的時候用到,在m文件中還是需要使用#import 而#import比起#include的好處就是不會引起重復包含。
42. 類別的作用?
答:有時我們需要在一個已經定義好的類中增加一些方法,而不想去重寫該類。可以使用類別對該類擴充新的方法。
注意:類別只能擴充方法,而不能擴充成員變量。
代理的作用
委托代理(degegate),目的是改變和傳遞控制鏈
顧名思義,把某個對象要做的事情委托給別的對象去做。那么別的對象就是這個對象的代理,代替它來打理要做的事。反映到程序中,首先要明確一個對象的委托方是哪個對象,委托所做的內容是什么。
委托機制是一種設計模式。
多態:子類的指針可以賦值給父類
43.鏈表和數組的區別在哪里?
二者都屬於一種數據結構
從邏輯結構來看
1. 數組必須事先定義固定的長度(元素個數),不能適應數據動態地增減的情況。當數據增加時,可能超出原先定義的元素個數;當數據減少時,造成內存浪費;數組可以根據下標直接存取。
2. 鏈表動態地進行存儲分配,可以適應數據動態地增減的情況,且可以方便地插入、刪除數據項。(數組中插入、刪除數據項時,需要移動其它數據項,非常繁瑣)鏈表必須根據next指針找到下一個元素
從內存存儲來看
1. (靜態)數組從棧中分配空間, 對於程序員方便快速,但是自由度小
2. 鏈表從堆中分配空間, 自由度大但是申請管理比較麻煩
從上面的比較可以看出,如果需要快速訪問數據,很少或不插入和刪除元素,就應該用數組;相反, 如果需要經常插入和刪除元素就需要用鏈表數據結構了。
44. 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],執行結果是2,5
&a+1不是首地址+1,系統會認為加一個a數組的偏移,是偏移了一個數組的大小(本例是5個int)
int *ptr=(int *)(&a+1);則ptr實際是&(a[5]),也就是a+5
原因如下:&a是數組指針,其類型為 int (*)[5];
而指針加1要根據指針類型加上一定的值,不同類型的指針+1之后增加的大小不同。
a是長度為5的int數組指針,所以要加 5*sizeof(int),所以ptr實際是a[5],
但是prt與(&a+1)類型是不一樣的(這點很重要),所以prt-1只會減去sizeof(int*)
a,&a的地址是一樣的,但意思不一樣
a是數組首地址,也就是a[0]的地址,&a是對象(數組)首地址, a+1是數組下一元素的地址,即a[1],&a+1是下一個對象的地址,即a[5].
45. 寫一個委托的interface
@protocol MyDelegate;
@interface MyClass: NSObject
{ id <MyDelegate> delegate; }
//委托方法@protocol MyDelegate- (void)didJobs:(NSArray *)args;
@end
46. 寫一個NSString類的實現
+(id)initWithCString:(const char *)nullTerminatedCStringencoding:(NSStringEncoding)encoding;
+ (id)stringWithCString: (const char*)nullTerminatedCString encoding: (NSStringEncoding)encoding
{ NSString *obj;
obj = [selfallocWithZone: NSDefaultMallocZone()];
obj = [objinitWithCString: nullTerminatedCString encoding: encoding];
returnAUTORELEASE(obj);
}
47. 關鍵字const有什么含意?修飾類呢?static的作用,用於類呢?還有extern c的作用
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的出現。
(1)欲阻止一個變量被改變,可以使用 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關鍵字的作用:
(1)函數體內 static 變量的作用范圍為該函數體,不同於 auto 變量,該變量的內存只被分配一次,因此其值在下次調用時仍維持上次的值; (2)在模塊內的 static 全局變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
(3)在模塊內的 static 函數只可被這一模塊內的其它函數調用,這個函數的使用范圍被限制在聲明 它的模塊內;
(4)在類中的 static 成員變量屬於整個類所擁有,對類的所有對象只有一份拷貝;
(5)在類中的 static 成員函數屬於整個類所擁有,這個函數不接收 this 指針,因而只能訪問類的static 成員變量。
extern "C"的作用:
(1)被 extern "C"限定的函數或變量是 extern 類型的;
extern是 C/C++語言中表明函數和全局變量作用范圍(可見性)的關鍵字,該關鍵字告訴編譯器,其聲明的函數和變量可以在本模塊或其它模塊中使用。
(2)被 extern "C"修飾的變量和函數是按照 C 語言方式編譯和連接的;
extern "C"的慣用法
(1)在 C++中引用 C 語言中的函數和變量,在包含 C 語言頭文件(假設為 cExample.h)時,需進 行下列處理:
extern "C" { #include "cExample.h" }
而在 C語言的頭文件中,對其外部函數只能指定為 extern 類型,C語言中不支持 extern "C"聲明, 在.c 文件中包含了 extern "C"時會出現編譯語法錯誤。
(2)在 C 中引用 C++語言中的函數和變量時,C++的頭文件需添加 extern "C",但是在 C 語言中不 能直接引用聲明了 extern "C"的該頭文件,應該僅將 C 文件中將 C++中定義的extern "C"函數聲明為 extern 類型。
48.為什么標准頭文件都有類似以下的結構?
#ifndef __INCvxWorksh
#define __INCvxWorksh
#ifdef __cplusplus
extern "C" {
#endif /*...*/
#ifdef __cplusplus
}
#endif
#endif /* __INCvxWorksh */
顯然,頭文件中的編譯宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用是防止該頭文件被重復引用。
49. #import跟#include的區別,@class呢?
@class一般用於頭文件中需要聲明該類的某個實例變量的時候用到,在m文件中還是需要使用#import而#import比起#include的好處就是不會引起交叉編譯。
50.線程與進程的區別和聯系?
答:進程和線程都是由操作系統所體會的程序運行的基本單元,系統利用該基本單元實現系統對應用的並發性。
程和線程的主要差別在於它們是不同的操作系統資源管理方式。
進程有獨立的地址空間,一個進程崩潰后,在保護模式下不會對其它進程產生影響,而線程只是一個進程中的不同執行路徑。
線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等於整個進程死掉,所以多進程的程序要比多線程的程序健壯,但在進程切換時,耗費資源較大,效率要差一些。但對於一些要求同時進行並且又要共享某些變量的並發操作,只能用線程,不能用進程。
51.列舉幾種進程的同步機制,並比較其優缺點。
答案:原子操作、信號量機制、自旋鎖、管程、會合、分布式系統
進程之間通信的途徑
答案:共享存儲系統消息傳遞系統管道:以文件系統為基礎
進程死鎖的原因
答案:資源競爭及進程推進順序非法
死鎖的4個必要條件
答案:互斥、請求保持、不可剝奪、環路
死鎖的處理
答案:鴕鳥策略、預防策略、避免策略、檢測與解除死鎖
52.什么是鍵-值,鍵路徑是什么
答:模型的性質是通過一個簡單的鍵(通常是個字符串)來指定的。視圖和控制器通過鍵來查找相應的屬性值。在一個給定的實體中,同一個屬性的所有值具有相同的數據類型。鍵-值編碼技術用於進行這樣的查找—它是一種間接訪問對象屬性的機制。
鍵路徑是一個由用點作分隔符的鍵組成的字符串,用於指定一個連接在一起的對象性質序列。第一個鍵的性質是由先前的性質決定的,接下來每個鍵的值也是相對於其前面的性質。鍵路徑使您可以以獨立於模型實現的方式指定相關對象的性質。通過鍵路徑,您可以指定對象圖中的一個任意深度的路徑,使其指向相關對象的特定屬性。
For example, the keypath address.streetwould get the value of the address property from thereceivingobject, and then determine the street property relative to the addressobject.
53.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.
54.目標-動作機制
答:目標是動作消息的接收者。一個控件,或者更為常見的是它的單元,以插座變量(參見"插座變量"部分) 的形式保有其動作消息的目標。
動作是控件發送給目標的消息,或者從目標的角度看,它是目標為了響應動作而實現的方法。程序需要某些機制來進行事件和指令的翻譯。這個機制就是目標-動作機制。
55. cocoa touch框架
這些框架包括:
Core Animation
通過Core Animation,您就可以通過一個基於組合獨立圖層的簡單的編程模型來創建豐富的用戶體驗。
Core Audio
Core Audio是播放,處理和錄制音頻的專業技術,能夠輕松為您的應用程序添加強大的音頻功能。
Core Data提供了一個面向對象的數據管理解決方案,它易於使用和理解,甚至可處理任何應用或大或小的數據模型。
功能列表:框架分類
下面是 Cocoa Touch 中一小部分可用的框架:
音頻和視頻
CoreAudio
OpenAL
MediaLibrary
AVFoundation
數據管理
Core Data
SQLite
圖形和動畫
CoreAnimation
OpenGL ES
Quartz 2D
網絡/li>
Bonjour
WebKit
BSDSockets
用戶應用
AddressBook
CoreLocation
MapKit
StoreKit
56.objc的內存管理
答:如果您通過分配和初始化(比如[[MyClass alloc] init])的方式來創建對象,您就擁有這個對象,需要負責該對象的釋放。這個規則在使用NSObject的便利方法new 時也同樣適用。
如果您拷貝一個對象,您也擁有拷貝得到的對象,需要負責該對象的釋放。如果您保持一個對象,您就部分擁有這個對象,需要在不再使用時釋放該對象。反過來,如果您從其它對象那里接收到一個對象,則您不擁有該對象,也不應該釋放它(這個規則有少數的例外,在參考文檔中有顯式的說明)。
57.自動釋放池是什么,如何工作?
答:當您向一個對象發送一個autorelease消息時,Cocoa就會將該對象的一個引用放入到最新的自動釋放池。它仍然是個正當的對象,因此自動釋放池定義的作用域內的其它對象可以向它發送消息。當程序執行到作用域結束的位置時,自動釋放池就會被釋放,池中的所有對象也就被釋放。
1)ojc-c是通過一種"referring counting"(引用計數)的方式來管理內存的, 對象在開始分配內存(alloc)的時候引用計數為一,以后每當碰到有copy,retain的時候引用計數都會加一, 每當碰到release和autorelease的時候引用計數就會減一,如果此對象的計數變為了0, 就會被系統銷毀.
2) NSAutoreleasePool就是用來做引用計數的管理工作的,這個東西一般不用你管的.
3)autorelease和release沒什么區別,只是引用計數減一的時機不同而已,autorelease會在對象的使用真正結束的時候才做引用計數減一。
58.類工廠方法是什么?
答:類工廠方法的實現是為了向客戶提供方便,它們將分配和初始化合在一個步驟中,返回被創建的對象,並進行自動釋放處理。這些方法的形式是+ (type)className...(其中 className不包括任何前綴)。工廠方法可能不僅僅為了方便使用。它們不但可以將分配和初始化合在一起,還可以為初始化過程提供對象的分配信息。類工廠方法的另一個目的是使類(比如NSWorkspace)提供單件實例。雖然init...方法可以確認一 個類在每次程序運行過程只存在一個實例,但它需要首先分配一個“生的”實例,然后還必須釋放該實例。工廠方法則可以避免為可能沒有用的對象盲目分配內存。
59. 單件實例是什么?
Foundation和Application Kit 框架中的一些類只允許創建單件對象,即這些類在當前進程中的唯一實例。舉例來說,NSFileManager和NSWorkspace 類在使用時都是基於進程進行單件對象的實例化。當向這些類請求實例的時候,它們會向您傳遞單一實例的一個引用,如果該實例還不存在,則首先進行實例的分配和初始化。單件對象充當控制中心的角色,負責指引或協調類的各種服務。如果類在概念上只有一個實例(比如NSWorkspace),就應該產生一個單件實例,而不是多個實例;如果將來某一天可能有多個實例,您可以使用單件實例機制,而不是工廠方法或函數。
60.動態綁定
—在運行時確定要調用的方法
動態綁定將調用方法的確定也推遲到運行時。在編譯時,方法的調用並不和代碼綁定在一起,只有在消實發送出來之后,才確定被調用的代碼。通過動態類型和動態綁定技術,您的代碼每次執行都可以得到不同的結果。運行時因子負責確定消息的接收者和被調用的方法。運行時的消息分發機制為動態綁定提供支持。當您向一個動態類型確定了的對象發送消息時,運行環境系統會通過接收者的isa指針定位對象的類,並以此為起點確定被調用的方法,方法和消息是動態綁定的。而且,您不必在Objective-C 代碼中做任何工作,就可以自動獲取動態綁定的好處。您在每次發送消息時,特別是當消息的接收者是動態類型已經確定的對象時,動態綁定就會例行而透明地發生。
61.obj-c的優缺點objc
優點:
1) Cateogies 2) Posing 3) 動態識別 4) 指標計算 5)彈性訊息傳遞 6) 不是一個過度復雜的 C 衍生語言 7) Objective-C 與 C++ 可混合編程
缺點:
1) 不支援命名空間 2) 不支持運算符重載 3) 不支持多重繼承 4) 使用動態運行時類型,所有的方法都是函數調用,所以很多編譯時優化方法都用不到。(如內聯函數等),性能低劣。
62.sprintf,strcpy,memcpy使用上有什么要注意的地方?
答:strcpy是一個字符串拷貝的函數,它的函數原型為strcpy(char *dst, const char *src);將src開始的一段字符串拷貝到dst開始的內存中去,結束的標志符號為'\0',由於拷貝的長度不是由我們自己控制的,所以這個字符串拷貝很容易出錯。
具備字符串拷貝功能的函數有memcpy,這是一個內存拷貝函數,它的函數原型為memcpy(char *dst,const char* src, unsigned int len);將長度為len的一段內存,從src拷貝到dst中去,這個函數的長度可控。但是會有內存疊加的問題。
sprintf是格式化函數。將一段數據通過特定的格式,格式化到一個字符串緩沖區中去。sprintf格式化的函數的長度不可控,有可能格式化后的字符串會超出緩沖區的大小,造成溢出。