Objective C介紹與MVC
iOS 架構
iOS Core OS 以C語言為基礎建立 底層網路存取、外部裝置存取、作業系統層級處理,如:記憶體、檔案、執行緒處理 Accelerate Framework:執行複雜數學、向量、數位訊號、影像處理等 --External Accessory Framework:存取外部裝置 --Security Framework:與外部存取的安全機制,如:認證、金鑰等 --System :作業系統核心(UNIX-like)、驅動程式等 Core Services Core OS Media Services Cocoa Touch iOS主要分成四層:Core OS、Core Services、Media、Cocoa Touch, Core OS是以C語言為基礎的系統架構,底層網路存取、外部裝置存取、作業系統層級處理,如:記憶體、檔案、執行緒處理 如: --Accelerate Framework:執行複雜數學、向量、數位訊號、影像處理等 --External Accessory Framework:存取外部裝置 --Security Framework:與外部存取的安全機制,如:認證、金鑰等 --System :作業系統核心(UNIX-like)、驅動程式等 以C語言為基礎建立
iOS Core Services 以C語言為基礎建立 提供上面兩層的框架建立與包裝 CFNetwork Framework: C語言的TCP/IP網路介面和低階網路存取 Core Foundation Framework: C語言框架,提供資料型態、時間、日期、執行緒處理等,這些功能有被包裝成Objective-C的Foundation Framework Core Location Framework:位置存取 Store Kit Framework:與Apple App Store交易處理 SQLite library:資料庫 … Core Services Core OS Media Services Cocoa Touch Core Services是以C語言為基礎的系統架構,多數提供上面兩層框架的建立與包裝 如: --CFNetwork Framework: C語言的TCP/IP網路介面和低階網路存取 --Core Foundation Framework: C語言框架,提供資料型態、時間、日期、執行緒處理等,這些功能有被包裝成Objective-C的Foundation Framework --Core Location Framework:位置存取 --Store Kit Framework:與Apple App Store交易處理 --SQLite library:資料庫 … 以C語言為基礎建立
iOS Media Services 聲音、影像、動畫、圖形處理 以C語言和 Objective C 為基礎建立 Media Player Framework:播放不同格式的影像 Core Audio Frameworks:播放、錄製不同聲音格式 OpenGL ES:2D、3D圖形處理 Quartz:動畫處理 Core Midi Framework:MIDI格式處理 … Core Services Core OS Media Services Cocoa Touch 媒體層是以C語言和Objective-c為基礎建立,主要服務包括聲音、影像、動畫、圖形處理 如: --Media Player Framework:播放不同格式的影像 --Core Audio Frameworks:播放、錄製不同聲音格式 --OpenGL ES:2D、3D圖形處理 --Quartz:動畫處理 --Core Midi Framework:MIDI格式處理 …等 以C語言和 Objective C 為基礎建立
iOS Cocoa Touch 以 Objective-C 撰寫 包含許多應用程式開發所需的框架 UIKit Framework:使用者介面建立與管理、事件處理、多工、感測器、藍芽等 Map Kit Framework:地圖 Social Framework:Twitter, Facebook等社群網站 SpriteKit Framework:2D遊戲 iAd Framework:廣告 Address Book UI Framework:通訊錄 … Core Services Core OS Media Services Cocoa Touch 最上層Cocoa Touch提供了iOS大部分應用程式開發所需的框架, 如: --UIKit Framework:使用者介面建立與管理、事件處理、多工、感測器、藍芽等 --Map Kit Framework:地圖 --Social Framework:Twitter, Facebook等社群網站 --SpriteKit Framework:2D遊戲 --iAd Framework:廣告 --Address Book UI Framework:通訊錄 …等 以 Objective-C 撰寫
Objective-C
Objective-C 簡介 以C語言為基礎,加入物件導向特性擴充而成的 全新語言 應用於MAC OS X和iOS這兩個作業系統 任何原始的C語言程式都可以通過Objective-C編 譯器而不需修改 允許在Objective-C內使用任何原始的C語言代碼
類別與物件 Car 類別, class 定義 外觀、樣式、特性(變數,屬性):door、color 動作(方法):start()、stop() Car 類別:像是一個藍圖/樣板,定義之後會被建造出來樣子,如:定義會執行哪些動作(方法, method),具有哪些外觀、樣式、特性(儲存資料的變數) 如車子樣板:會定義是幾門的車子、車子顏色、啟動的動作、停止的動作等 物件則是依據類別藍圖,產生出來的實體(配置一塊記憶體空間,儲存該藍圖的資料),同一個類別可以產生出很多該藍圖的物件。 如:依據該車子樣板,產生出一個2門土黃色車子、一個3門紅色車子等 alloc, init new 產生物件(Object, instance) …… 記憶體 color:土黃色 door:2 start() stop() color:紅色 door:3 start() stop()
類別宣告 類別分成兩個檔案 類別、資料、方法的宣告 類別的實作(implement) ,方法的內容程式碼 放在.h檔 宣告內容需放在@interface 和@end之間 類別的實作(implement) ,方法的內容程式碼 放在.m檔 實作內容需放在@ implementation 和@end之間 類別可全部放在同一個檔案中或是分成兩個檔案。 類別、資料、方法的宣告會放在.h檔中,宣告內容需放在@interface 和@end之間 類別的實作(implement) 、方法的內容程式碼會放在.m檔中,實作內容需放在@ implementation 和@end之間
Objective-C擴充的資料型態 類型 說明 BOOL 布林值,儲存YES/true(1)或 NO/false(0)資料 id 通用類型,是一個指向任何一個繼承NSObject類別的物件指標,因為本身已為指標所以不用再加上星號 nil 和C語言的NULL相同,表示指向一個空的物件 IBOutlet 主要用來給Interface Builder工具提示用,用來連接變數與元件 IBAction 主要用來給Interface Builder工具提示用,用來連接方法與元件事件 Objective-C除了基本的資料類型以外,還定義了一些資料型態如BOOL、id、nil、IBOutlet與IBAction BOOL:用來儲存布林值,真的值為:YES或true或1,假的值為: NO或false或0 id:通用資料型態,指向任何一個繼承NSObject類別的物件指標,因為本身已為指標所以不用再加上星號,也就是說編譯器不會特別去檢查物件的類型 nil:和C語言的NULL相同,表示指向一個空的物件 IBOutlet和IBAction主要用來給Interface Builder工具提示使用,如在介面設計中的某元件要對應到類別程式中的某屬性時,必須透過Interface Builder工具將元件與屬性做連接,連接時Interface Builder工具只能連接定義資料型態為IBOutlet的屬性。同樣的在介面設計中,要設定某元件在觸發某事件時(如:在元件上按下並在元件上放開時),要執行類別程式中的某方法時,必須透過Interface Builder工具將元件事件與該方法做連接,連接時Interface Builder工具只能連接定義為IBAction的方法
訊息傳遞(Message passing) Java中物件呼叫方法, Objective-C 裡,不 稱為呼叫方法,稱為傳遞訊息 方法的宣告 無參數的方法 - ( void ) someMethod; + ( void ) someMethod; 多參數 ( void ) someMethod: (float) data withTag: (int) tag; 類似C語言:void someMethodwithTag(float data, int tag); 在Java中,物件要執行某方法,通常稱為呼叫方法,在 Objective-C 中,不稱為呼叫方法,稱為傳遞訊息 方法的宣告也與Java不同,宣告方式如下: --沒有參數的方法 - ( void ) someMethod; 減號代表是物件方法,屬於該物件的,需產生物件之後才能呼叫該方法,如前面例子,土黃色車中的start()和stop()方法,紅色車中的start()和stop()方法,每個物件有它自己的start()和stop()方法。減號後要加上括號(資料型態) ,表示方法執行後回傳值的資料型態(return xxx;),若沒有return,用void表示。方法最後直接加分號,表示不需要傳入資料到該方法中。 + ( void ) someMethod; 加號代表是類別方法,屬於任何物件共用的,只會有一個,不需產生物件就能呼叫該方法 --具有多個參數的方法 - ( void ) someMethod: (float) data withTag: (int) tag;若方法需輸入資料,使用冒號:,冒號後加上括號(資料型態)表示方法要輸入的資料型態,括號後加上變數名稱,第二個輸入參數通常會再給一個方法名稱,通常用來表示第二個參數的意義,如:withTag,方法名稱後與前述第一個參數相同,此方法名稱為 someMethod:withTag: 。這個方法類似Java或C語言這個方法 void someMethodwithTag(float data, int tag); “-” : 物件方法 “+” : 類別方法,不需產生物件實體就可以呼叫
訊息傳遞(Message passing) Java物件呼叫方法 ↔ Objective-C物件訊息傳遞 多參數 obj.someMethod(arg); [obj someMethod: arg]; Java物件呼叫方法的方式是使用點號,如:obj.someMethod(arg); Objective-C物件訊息傳遞(呼叫方法)是使用中括號[ ],如[obj someMethod: arg]; 多參數時 Java obj.someMethodwithTag(arg1, arg2); Objective-C[obj someMethod:arg1 withTag:arg2]; [obj someMethod:arg1 withTag :arg2];
繼承 和 #include 完全相似,但不會重複載入同一個標頭檔 #import "class.h" @interface Car:NSObject { int _door; } - (void) setDoor: (int) door; - (int)door; @end 子類別 父類別 若在類別中需要用到別的類別(API)的東西,需使用#import <xxxx.h> 或是 #import "xxxx.h",前者是iOS API框架中定義的,後者是開發者自行定義的, #import和 #include 完全相似,但#import不會重複載入同一個標頭檔 @interface 之後的名稱表示類別名稱,冒號後表示此類別繼承的類別,如投影片範例表示此程式為宣告一個Car類別,繼承NSObject,Car為NSObject的子類別,NSObject為Car的父類別 物件導向中繼承表示子類別具有該父類別宣告的東西,無需重新自行定義,從頭打造,只需增加此類別需擴充的方法、屬性,若繼承過來的方法不合用或是需要進行擴充,可在子類別中,重新定義覆寫,但需方法定義與父類別相同(回傳值資料型態、方法名稱、輸入參數型態和個數) Note: NSObject是標準基礎類別,所有新類別都需繼承此類別(直接或間接繼承),定義在the Objective-C Foundation framework 中,裡面重要方法,如: + (id)alloc; 進行記憶體配置,產生儲存類別樣板的空間,回傳值為呼叫此方法的類別物件 - (id)init; 進行物件初始化動作
類別宣告(Car.h) @interface Car:NSObject { int _door; } - (void) setDoor: (int) door; - (int)door; @end 實體變數(instance variable)宣告 類別中的實體變數需告需寫在大括號中{} 預設宣告的實體變數皆為私有的,除了本身這個類別可以存取外,在別的類別中無法存取。 若要在別的類別中存取此物件變數,需宣告成@public int _door; 在別的類別中要使用->存取,如: obj->_door=3; 方法宣告 預設在別的類別中無法直接存取此物件變數,若需公開需宣告成@public int _door;在別的類別中要使用->存取
類別實作(Car.m) #import "Car.h" @implementation Car -(void) setDoor:(int) door { _door=door; } - (int)door{ return _door; @end 在.h檔中宣告的方法,需在.m檔中將該方法內容轉寫出來
創建物件 Objective-C 建立物件需透過兩個方法 + (id)alloc; (id)init; 配置記憶體空間 物件初始化 NSObject類別中所定義 NSObject類別中定義物件創建方法 + (id)alloc; 進行記憶體配置,產生儲存類別樣板的空間,回傳值為呼叫此方法的類別物件 - (id)init; 進行物件初始化動作 Objective-C 建立物件時需先呼叫NSObject類別中的alloc類別方法 ,如:Car * myCar = [Car alloc]; 接著呼叫NSObject類別中的init物件方法,如: myCar = [myCar init]; 在Objective-C中多個方法呼叫可進行合併成一行撰寫,如: Car * myCar = [[Car alloc] init]; Car * myCar = [Car alloc]; myCar = [myCar init]; Car * myCar = [[Car alloc] init];
初始化 -(id) init{ if(self=[super init]){ //初始化 } return self; 客製化init -(id) init: (int) num{ if(self=[super init]){ //初始化 _door=num; } return self; 預設NSObject中init初始化方法是沒有輸入參數,若開發者希望建立物件,即進行一些物件變數或屬性質的設定,可進行客製化init方法 若不需傳入參數,只需覆寫init方法,其程式內容範本如下: -(id) init{ if(self=[super init]){ //初始化 } return self; super是父類別物件指標,在此是呼叫父類別的init物件方法,進行物件初始化工作,若物件成功建立會回傳該物件,或失敗會回傳nil self是指向自身物件的指標,在if判斷式中若呼叫父類別的init方法成功會將物件儲存到self中,若失敗self為nil 若物件建立成功,可在if判斷式中進行物件變數設定等初始化工作。
常用類別—NSString 初始化物件方法 -(id)init 初始化物件 -(id)initWithCString: (const char*)cstring encoding: (NSStringEncoding *) encoding 透過C的字串來建構 NSString *str =[[NSString alloc] initWithCString:"Wellcome" encoding:NSUTF8StringEncoding]; -(id)initWithFormat: (NSString *) format... initWithFormat:@"String %d” ,10]; NSString類別的初始化物件方法,需要先呼叫alloc,再呼叫init等方法 -(id)init初始化物件,空字串 -(id)initWithCString (const char*)cstring encoding: (NSStringEncoding *) encoding 初始化物件,透過C的字串來建構一個NSString 物件,第一個參數為要轉換為NSString物件的字元陣列,第二個參數為編碼方式 如: NSString *str =[[NSString alloc] initWithCString:"Wellcome" encoding:NSUTF8StringEncoding]; -(id)initWithFormat: (NSString *) format...初始化物件,參數為格式化字串,在字串中使用%d、%f、%@等符號,將後面對應順序的變數資料取代。%格式,會依據要取代的變數資料型態不同而有不同標示方式,詳見後面第23頁投影片。 如: NSString *str =[[NSString alloc] initWithFormat:@"String %d" ,10];此最終NSString字串為"String 10"
NSString靜態方法與其他屬性 + (id) stringWithFormat:(NSString *)format,… +(id) stringWithString: (NSString *) string 複製另一個NSString內容 格式轉換 (double) doubleValue (float) floatValue (int) intValue … -(NSUInteger)length NSString靜態方法只需透過類別名稱呼叫,不需產生物件 +(id) stringWithFormat:(NSString *)format,…此方法會將參數為格式化字串產生一個NSString物件 如:NSString *str =[NSString stringWithFormat:@"String %d" ,10];此最終NSString字串為"String 10" +(id) stringWithString: (NSString *) string此方法會將參數的NSString內容複製產生一個NSString物件 NSString物件資料格式轉換屬性 (double) doubleValue 字串轉換為double值 (float) floatValue字串轉換為float值 (int) intValue字串轉換為int值 … 如: NSString *str =[NSString stringWithFormat:@"%f" ,10.5]; double price=str.doubleValue; NSString物件方法 -(NSUInteger)length字串長度
Logging NSLog(),將參數字串印於debug 區域中的 Console 視窗上 類似於C語言中的printf()函式,參數為格式化字串 要印出物件必須使用%@ char name[5] = "Eric"; NSLog(@"His name is %s .",name); NSLog()方法將參數字串印於debug 區域中的Console 視窗上,類似於C語言中的printf()函式,參數為格式化字串 如: char name[5] = "Eric"; NSLog(@"His name is %s .",name); 要印出字元陣列,需使用%s 要印出物件必須使用%@ NSSting *name= @"Eric"; NSLog(@"His name is %@ .",name); 其他格式請見下頁投影片 NSSting *name= @"Eric"; NSLog(@"His name is %@ .",name);
輸出格式 資料型態 所佔byte數 輸出格式 char 1 %c int 4 %d float %f double 8 short int 2 %hd long int %ld long double 16 %Lf unsigned int %u unsigned short int %hu unsigned long int %lu 表格中列出不同資料型態需使用的%格式
輸出視窗 顯示關閉debug區域視窗 NSLog()印出資訊將呈現在下方debug區域中 debug區域視窗
Setter 和 Getter 在Objective-C裡定義的成員,預設是不能直接 存取,因此一般會透過定義method來存取成員的 值
Car.h @interface Car:NSObject { int _door; } - (void) setDoor: (int) door; - (int) door; @end 此範例中宣告一個_door物件成員,但除了Car類別外,其他類鱉無法存取,因為對應會產生兩個方法 - (void) setDoor: (int) door;此方法為設定_door物件變數的值稱為Setter 和 - (int) door; 此方法為取得_door物件變數的值稱為Getter Setter Getter
Car.m #import "Car.h" @implementation Car -(void) setDoor:(int) door { _door=door; } - (int)door{ return _door; @end 將.h定義的Setter和Getter方法實作出來 實作Setter 實作Getter
Objective-C屬性(Property) 物件成員都要個別產生Setter和Getter方法才能進 行資料存取,且會需要經常宣告,這種作法過於 繁複 在Objective-C可以用屬性的語法,自動產生 setter和getter的方法 由於物件成員都要個別產生Setter和Getter方法才能進行資料存取,在Objective C中使用了Property的語法,除了會產生物件成員外,會自動產生setter和getter的方法
@property (property-attributes) property-type property-name ; 屬性 允許對實體變數產生設定和取得方法 在.h檔中使用@property 宣告屬性 在.m檔中,需使用@synthesize 語法生成屬性,屬性 生成時,會產生對應的物件成員變數 在Xcode 4.4以上不用寫,會自動生成屬性名稱前加 上底線的物件成員變數 @property (property-attributes) property-type property-name ; 屬性語法的宣告方式 在.h檔中使用@property 宣告屬性 @property (property-attributes) property-type property-name ; property-attributes會於下頁中說明,property-type為屬性的資料/物件型態,property-name為屬性名稱 在.m檔中,需使用@synthesize 語法生成屬性,屬性生成時,會產生對應的物件成員變數 @synthesize propertyName; //生成時,屬性名稱與對應的物件成員變數名稱相同 @synthesize propertyName = _myInstanceVariable; ; //生成時,屬性名稱與對應的物件成員變數名稱 在Xcode 4.4開始不用寫@synthesize ,會自動生成屬性名稱前加上底線的物件成員變數 @synthesize propertyName; @synthesize propertyName = _myInstanceVariable;
Property attributes strong : 強參照指向此物件,有強參照指向的物件不會消 失 weak : 若參照,當沒有強參照參考到此物件,此物件會 消失 assign :設定給屬性的值會被直接指派給實體變數 copy :把指派給此屬性的物件做一個複本,指向該複本, 而不是直接指向指派給此屬性的物件 nonatomic :告訴編譯器,不用額外產生程式碼來保證執 行緒的安全 readwrite : 會建立getter 和 setter方法 (預設值) readonly :只能進行讀取,不能被設定,編譯器只會產生 getter讀取的方法 @property 宣告的( )中需表示此屬性的參照與存取方式,可有以下設定 strong : 強參照指向此物件,有強參照指向的物件不會消失 weak : 若參照,當沒有強參照參考到此物件,此物件會消失 assign :設定給屬性的值會被直接指派給實體變數 copy :把指派給此屬性的物件做一個複本,指向該複本,而不是直接指向指派給此屬性的物件 nonatomic :告訴編譯器,不用額外產生程式碼來保證執行緒的安全 readwrite : 會建立getter 和 setter方法 (預設值) readonly :只能進行讀取,不能被設定,編譯器只會產生getter讀取的方法
ARC Automatic Reference Counting iOS 5開始加入的方式 不需使用者進行relaese, autorelease, retain等動作, 系統會自行處理 透過語法,讓編譯器在編譯時,自動產生管理 物件參照計數器的程式碼 強參照 弱參照 ARC不是垃圾回收(GC) ARC(Automatic Reference Counting):自動參照計數,這是在iOS 5中提出的方式,在以前撰寫程式時,只要使用alloc 、retain或是new等方式產生物件,必須將其記憶體釋放,若忘記,很容易產生記憶體洩漏(memory leakage),在記憶體管理上比較麻煩,因此iOS 5開始提出ARC方式,透過語法,讓編譯器在編譯時,自動產生管理物件參照計數器的程式碼,此方式並非垃圾回收(Garbage Collection)。 在ARC中,變數、物件成員、屬性宣告,將參照指標分成兩種:強參照、弱參照
強參照(Strong reference) @"Bob" ARC機制中,Objective C中預設為強參照 只要有參照,則該物件存在 沒有人參照,該則物件消失 First @"Bob" NSMutableString *First=[[NSMutableString alloc]initWithString:@"Bob"]; 在objective c中宣告物件變數都屬於強參照,範例如下: 圖中實線表示強參照,虛線表示弱參照 NSMutableString *First=[[NSMutableString alloc]initWithString:@"Bob"]; First物件變數使用強參照指向@"Bob" NSMutableString*aFirst=First; First參照指派給aFirst,因此aFirst物件變數也使用強參照指向@"Bob" First=[[NSMutableString alloc]initWithFormat:@"%@",@"John"]; First物件變數使用強參照改指向@"John",@"Bob"尚有aFirst指向 NSMutableString *oFirst=First; First參照指派給oFirst,因此oFirst物件變數也使用強參照指向@"John" aFirst=oFirst; oFirst參照指派給aFirst,因此aFirst物件變數也使用強參照指向@"John",此時@"Bob"沒有人指向,因此@"Bob"物件將被清除 NSMutableString*aFirst=First; First=[[NSMutableString alloc]initWithFormat:@"%@",@"John"]; NSMutableString *oFirst=First; First aFirst aFirst=oFirst; @"Bob" @"Bob" @"John" @"John" @"John" @"Bob" oFirst First aFirst First aFirst aFirst First oFirst
弱參照(Weak reference) NSMutableString *First=[[NSMutableString alloc]initWithString:@"Bob"]; __weak NSMutableString*aFirst=First; First=[[NSMutableString alloc]initWithFormat:@"%@",@"John"]; @"Bob" @"Bob" @"Bob" @"John" 圖中實線表示強參照,虛線表示弱參照 若要在Objective中宣告弱參照,需使用__weak關鍵字(weak前有兩個底線) NSMutableString *First=[[NSMutableString alloc]initWithString:@"Bob"]; First物件變數使用強參照指向@"Bob" __weak NSMutableString*aFirst=First; First參照指派給aFirst,但aFirst為弱參照,因此aFirst物件變數使用弱參照指向@"Bob" First=[[NSMutableString alloc]initWithFormat:@"%@",@"John"]; First物件變數使用強參照改指向@"John",此時@"Bob"只剩下aFirst的弱參照無強參照指向,因此會消失,aFirst會指向nil nil First First aFirst aFirst First
@property strong weak copy assign retain __strong __weak __unsafe_unretained :與__weak相同,但不將其指向 nil retain @property屬性宣告語法中的property-attributes與強弱參照的對應關係如下: strong__strong weak__weak copy__strong assign__unsafe_unretained 與__weak相同,但不將其指向nil retain__strong
assign用於非指標 #import <Foundation/Foundation.h> @interface Car : NSObject @property(nonatomic,strong)NSString *color; @property(nonatomic,assign)int door; -(void) carInfo; @end @property屬性宣告語法中的assign用於非指標屬性宣告,如基本資料型態:int 、double、float等 #import "Car.h” @implementation Car -(void) carInfo { NSLog(@"color:%@",self.color); NSLog(@“door:%d”,self.door); } @end
屬性存取方式 用 . 或用訊息傳遞(方法呼叫) Ex: Car *c1=[[Car alloc]init]; c1.color=@"red"; c1.door=5; NSLog(@"color=%@ door=%d", c1.color, c1.door); [c1 setColor:@"yellow"]; [c1 setDoor:3]; NSLog(@"color=%@ door=%d", [c1 color], [c1 door]); 屬性存取方式可用 . 或用訊息傳遞(方法呼叫) 如Car類別中有兩個屬性:一個整數屬性door、一個NSString 屬性color Car *c1=[[Car alloc]init]; c1.color=@"red"; 使用.存取 c1.door=5; 使用.存取 NSLog(@"color=%@ door=%d", c1.color, c1.door); 使用.存取 [c1 setColor:@"yellow"]; 使用setter和getter方法存取 [c1 setDoor:3]; 使用setter和getter方法存取 NSLog(@"color=%@ door=%d", [c1 color], [c1 door]); 使用setter和getter方法存取
Car類別範例 #import <Foundation/Foundation.h> @interface Car : NSObject @property(nonatomic,strong)NSString *color; @property(nonatomic,assign)int door; -(void) carInfo; @end Car *c1=[[Car alloc]init]; c1.color=@"red"; c1.door=5; [c1 carInfo]; Car.h檔案內容 #import <Foundation/Foundation.h> @interface Car : NSObject @property(nonatomic,strong)NSString *color; @property(nonatomic,assign)int door; -(void) carInfo; @end Car.m檔案內容 #import "Car.h” @implementation Car -(void) carInfo { NSLog(@"door:%d",self.door); NSLog(@"color:%@",self.color); } 產生物件實體程式片段 Car *c1=[[Car alloc]init]; c1.color=@"red"; c1.door=5; [c1 carInfo]; #import "Car.h” @implementation Car -(void) carInfo { NSLog(@"door:%d",self.door); NSLog(@"color:%@",self.color); } @end
MVC (Model View Controller)
MVC iOS設計的基本精神:MVC Model:資料 View: UI Controller:控制整個程式的流程,如控制某個按鈕按下去的反應,也負責通知View有關model的資訊 iOS設計的基本精神:MVC Model:資料 View: UI Controller:控制整個程式的流程,如控制某個按鈕按下 去的反應,也負責通知View有關model的資訊
MVC Controller可以直接與Model和View溝通,但是 Model與View不能直接與Controller溝通(能間接) Model與Controller間接溝通方式 -- Model 透過廣播(Notification)方式,讓 Controller 知道資料有所變更 View與Controller間接溝通方式 --Action – Target :在Controller 中設定View某事件發生時,可以執行某個動作,此動作行為內容在 target 中,target 通常是 Controller。 --Delegate:在Controller 中設定一個代理者 (delegate) 給 View,這個代理者會處理許多事件,當遇到這些事件時,需呼叫代理者。這個代理者通常是 Controller。 --DataSource:Controller中設定一個資料來源者(dataSource) 給 View,這個資料來源者可以提供資訊,需要這些資訊需呼叫資料來源者,這個資料來源者通常是Controller 。 Controller可以直接與Model和View溝通,但是 Model與View不能直接與Controller溝通(能間接) Model不能與View直接或間接接觸
UIViewController UIViewController 提供了基本View的管理與控制, 擔任協調Model與View的角色 UIViewController是控制View的基本類別,負責載入和處理View,管理views之間的互動,協調處理資料物件,甚至要處理與其他controller互動,擔任協調Model與View的角色
Outlet is strong or weak? Outlet通常是weak,除非是File’s Owner在 nib檔中的頂層物件 通常在拉畫面時,是在一個ViewController中 指向的View(強參照)下加入子元件,因此建 立 Outlet時,只需給定弱參照即可 strong outlet通常已經在framework 類別中已 指定 UIViewController中的view會指向視窗的頂層view … Outlet 屬性宣告時,是要宣告為strong或是weak? 通常是weak,除非是File’s Owner(ViewController)在nib檔(UI檔)中的頂層物件。 通常在拉畫面時,是在一個ViewController中指向的View(強參照,為頂層物件)下加入子元件,因此建立 Outlet時,只需給定弱參照即可 strong outlet通常已經在framework 類別中已指定,如:UIViewController中的view會指向視窗的頂層view
實現表示強參照 虛線表示弱參照 viewController (UIViewController) view addSubView() 在拉畫面時,是在頂層View下加入UIView,也可以在程式中透過addSubView()方法來加入UIView 加入的UIView若需在程式中被控制,需在viewController宣告對應的屬性,此時屬性使用弱參照即可 view addSubView() UIView UIView UIView Outlet
弱參照(Weak reference) 在iOS framework中,有些UI類別會需指定dataSource(資料來源者)和delegate(事件代理者),此參照都為弱參照,因為在ViewController中會有強參照指向該UI類別(self.view)或是該UI類別元件是加在頂層View元件下的子元件 如圖中UITableView為此ViewController的頂層View,所以會有一個強參照self.view指向該UITableView元件。
常用類別—NSMutableString 物件方法 與NSString差異在於此物件中的字串內容可修改 - (void)appendFormat:(NSString *)format, ... 在原字串後加入格式化字串內容 - (void)appendString:(NSString *)aString - (void)deleteCharactersInRange:(NSRange)aRange 刪除參數範圍內的字 - (void)insertString:(NSString *)aString atIndex:(NSUInteger)anIndex 在參數anIndex位置插入參數aString字串 - (void)replaceCharactersInRange:(NSRange)aRange withString:(NSString *)aString 將參數aRange範圍內的字串取代為參數aString字串 …
常用類別—NSNumber 初始化方法 儲存數值的物件 - (NSNumber *)initWithBool:(BOOL)value - (NSNumber *)initWithChar:(char)value - (NSNumber *)initWithDouble:(double)value …
常用類別—NSNumber 產生物件的靜態方法 + (NSNumber *)numberWithBool:(BOOL)value + (NSNumber *)numberWithChar:(char)value + (NSNumber *) numberWithDouble:(double)value …
常用類別—NSNumber 取出數值的屬性 BOOL boolValue char charValue double doubleValue …
產生NSNumber物件方式 亦可使用@語法,產生NSNumber物件 NSNumber *number; number = @'A'; // Character number = @YES; // Boolean number = @43231ul // Unsigned Long number = @123431ll // Long Long number = @1254.23 // Float number = @123 // Integer number = @123.432 // Double
常用類別—NSArray 常用方法 +(id) arrayWithObjects: (id)first,… NSArray *data=[NSArray arrayWithObjects:@"Hello", [NSDate date],nil]; - (id) initWithObjects : (id)first,… NSArray * data= [[NSArray alloc] initWithObjects: :@"Hello", [NSDate date],nil]; - (NSUInteger)count - (id)objectAtIndex:(NSUInteger)index - (NSUInteger)indexOfObject: (id)anObject 物件1 物件2 NSArray可用來儲存多個不同型態的資料 產生物件的靜態方法 +(id) arrayWithObjects: (id)first,… 如: NSArray *data=[NSArray arrayWithObjects:@"Hello", [NSDate date],nil]; 產生具有2個資料的NSArray 物件,一個為NSString資料,一個為NSDate資料,最後要加上nil,表示NSArray 資料結尾 初始化物件方法,需先行呼叫alloc方法 - (id) initWithObjects : (id)first,… 如: NSArray * data= [[NSArray alloc] initWithObjects: :@"Hello", [NSDate date],nil]; - (NSUInteger)countNSArray物件資料筆數 - (id)objectAtIndex:(NSUInteger)index取出參數index索引值位置的資料 - (NSUInteger)indexOfObject: (id)anObject取出參數anObject物件在NSArray中的索引值位置
NSArray操作方式 產生NSArray物件 存取NSArray中的資料 使用@[]方式 NSArray * data; data = @[@"Hello", @"Hi", [NSDate date]]; 存取NSArray中的資料 使用[index] NSString *word = data[0]; data[0]=@"Hay";
常用類別—NSMutableArray 常用方法 與NSArray相同用來儲存多個不同型態的資料, 差異在於此物件中的資料可增加、刪除 - (void)addObject:(ObjectType)anObject - (void)insertObject:(ObjectType)anObject atIndex:(NSUInteger)index - (void)removeObject:(ObjectType)anObject - (void)removeObjectAtIndex:(NSUInteger)index - (void)replaceObjectAtIndex:(NSUInteger) indexwithObject:(ObjectType)anObject …
NSMutableArray操作方式 與NSArray相似,但在產生物件時需加上 mutableCopy NSArray * data; data = @[@"Hello", @"Hi", [NSDate date] mutableCopy];
常用類別—NSDictionary 常用方法 儲存的資料是一對對的key–value + (id)dictionaryWithObject:(ObjectType) anObject forKey:(id<NSCopying>)aKey + (id)dictionaryWithObjects: (NSArray<ObjectType> *)objects forKeys:(NSArray<id<NSCopying>> *)keys + (id)dictionaryWithObjectsAndKeys:(id) firstObject, ... NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys: @"value1", @"key1", @"value2", @"key2", nil];
常用類別—NSDictionary 常用方法和屬性 - (id)initWithObjectsAndKeys:(id)firstObject, ... - (ObjectType)objectForKey:(KeyType)aKey NSUInteger countreadonly NSArray < KeyType > *allKeys readonly, copy NSArray < ObjectType > *allValues readonly, copy
NSDictionary操作方式 產生NSDictionary物件 存取NSArray中的資料 使用@{}方式 NSDictionary *dict = @{@"key1" : @"value1", @"key2" : @"value2"}; 存取NSArray中的資料 使用[key] NSString *word = dict[@"key1"]; dict[@"key1"]=@"value11";
常用類別—NSDictionary 常用屬性
常用類別—NSArray 常用方法