標籤:
1, 從簡單的常式來看基本文法:
下面的代碼是通過OSX-Application-Command Line Tool產生的:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
NSLog(@"Hello, Objective-c");
}
return 0;
}
1>,檔案名稱:First_OSX_eg.m 這個是OC專用的副檔名,c語言的副檔名一般是用.c,庫檔案用.h;c++的副檔名一般用.cpp;
而OC的副檔名都是用.m(來自單詞message)不過這個只是闡述部分的副檔名,聲明部分的副檔名也是用.h,而且檔案名稱與對應.m的檔案是同名,如果副檔名為.mm則可以認為這個單元是c++代碼(c++是相容c的).
2>,#import相當於C語言中的#include,Delphi語言中的Uses,表示對庫檔案或其他單元的引用.雖然OC也相容#include,但是#import要比#include好得多,不管你在檔案中出現了多少次#import引用,編譯器對特定檔案就只引用一次.
#import之後所用的庫檔案,在文法上,使用雙引號或者角括弧都是允許的,但是一般系統預設為雙引號為本地標頭檔,
而角括弧裡跟的時系統標頭檔.
3>,<Foundation/Foundation.h>表示引用Foundation架構中的Foundation.h檔案.用花鍵+單點可以查看對應的單元檔案.其實,在引用系統庫時,一般頭
檔案都是幾十上百個標頭檔的集合.#import可以先行編譯標頭檔,使得引用速度加快. 例如Foundation.h對應的架構檔案可以在以下路徑進行查看:
/System/Library/Frameworks/Foundation.framework/Headers/ (後面版本的Headers目錄改成了Resources目錄).
4>,NSLog函數,其中NS表示OSX中基礎Cocoa庫,最早引用於Next-Step架構,其意義和用法基本等同於C語言中的printf(),但是其參數需要一個Cocoa庫
格式的字串.類似這樣的NS命名的函數還很多,例如:
NSArray: 用來定義一個數組
NSDateFormat: 格式化日期
NSThread:定義一個線程.
NSSpeechSyntheSizer:定義一個聲音.
5>,用@“xx”來表示一個字串,其中@的意義是指這個字串是一個Cocoa庫中的NSString字串,而不是傳統的C語言字串.作為一個Cocoa風格的字串,其功能
要比傳統的C語言字串強大得多.例如用StringWithFormat方法就可以用格式化字元(例如%d)格式化各種類型資料.
6>,花+~可以很方便的在多個工程中切換.
2, 常用的OC物件類型:
1>,UIView : 所有可視控制項的基類。基於此類的每一個對象都是一個容器。
2>,UILabel:標籤類
3>,UITextField:文本輸入類
4>,UIButton: 按鈕類
3, 常用的OC文法:
1>程式流程式控制制
a>, 選擇結構:
if(BOOL運算式)
{
運算式;
}
else
{
運算式;
}
b>,迴圈結構:
int i;
for(i=0; i<=99;i++)
{
NSLog(@“%d\n”,i);
}
或者
while(BOOL運算式)
{迴圈體}; //這個需要在迴圈體中對BOOL運算式進行控制.
c>,分支結構:
switch(運算式)
{
case 分支1數值: 運算式;
break;
case 分支2數值: 運算式;
break;
…
}
’ 2>, 函數定義:(注意,在Obj-c中,不允許在一個函數內部直接定義子函數.每個函數的作用範圍自動是從
上至下,可以通過聲明來作用全域,或者提供給其他單元介面),函數允許參數名與函數名同名.
如果函數的傳回值類型為一個類的對象,則函數應該用指標型,例如:
NSString *ShowMsg(int x1)
{
return([NSString stringWithFormat:@"%d",x1]);
}
如果是調用這個函數傳回值,可以用%@格式字串例如:
NSLog(@"%@",ShowMsg(123456));
關於預設的main函數定義:int main(int argc, const char *argv[])
其中,argc為程式的參數個數,argv為參數數組,其中argv[0]為程式檔案本身路徑+檔案名稱(這點與Delphi相同).
3>, 資料類型的定義(對於對象的定義一律用指標)
a>, 整型: int a;
b>, 字元類型: char c;
c>, 字串類型:
char s[n]; 這個相當於n長度的數組,而對應Cocoa庫則為NSArray. 這裡s即為一個指標,相當於字串對象名.
char s[]; 可以這麼定義一個變長的數組,Obj-c中的字串嚴格按對象處理,不像Delphi中那麼方便了.
可以用strlen(s)來返回一個字串的長度.
char *s[];可以用這個來定義一個多維陣列,其中每一個s[i]對應一個字串.
NSString str; 不過由於Obj-c中常使用Cocoa庫的NSString,所以大多數時候,盡量使用這個類型,它帶有很多方便的方法.
d>,BOOL類型: OC的布爾類型並不是true和false,而是YES和NO. 其本質是一個8位的帶符號的字元.定義時,1為YES,0為NO.在實際使用時,如果把其他符號
當作BOOL類型判斷,那麼只會判斷其最低位的值,而忽略高位值(注意這裡跟C語言不同,並不是大於0就為真).
對BOOL類型值的判斷,只能拿值與NO進行比較,如果相當為假,不等則為真.無法用BOOL類型與YES進行比較(雖然有時候用YES比較也恰好正確).
e>,浮點型float
f>,常量關鍵字const 這個可以加在定義類型前,例如:const char *argv[];
g>,枚舉類型的定義:
typedef enum{ 枚舉常量列表,逗號隔開} 枚舉類型名;
並沒有具體的內建函式可以直接得到枚舉常量名,可以自己構造一個函數來實現.
常用的枚舉定義技巧,可以定義一個起始量和一個終止量,這樣方便迴圈遍曆.
h>,結構體類型定義:
typedef struct{結構體元素定義}結構體類型名;
對結構體賦值可以直接用大括弧包含數值: stru1={1,’a’};
也可以用[結構體變數名.成員名]引用每一個成員進行賦值.
5>,更為複雜的一些Cocoa定義的有用資料類型.
a>NSRange:
typedef struct _NSRange{
unsigned int location;
unsigned int length;
} NSRange;
表示一段資料的起始位置以及資料長度.
可以利用快捷函數NSMakeRange()來返回一個NSRange
eg. NSRange range=NSMakeRange(17,4);
b>若干幾何資料類型:NSPoint, NSSize,NSRect
對應快捷函數NSMakePoint(), NSMakeSize(),NSMakeRect()
typedef struct _NSPoint{
float x;
float y;
} NSPoint;
typedef struct _NSSize{
float width;
float height;
}NSSize;
typedef struct _NSRect{
NSPoint origin;
NSSize size;
}NSRect;
c> NSString, 相比c語言中的字串與字元數組的關係,不需要再考慮0操作字元.
6>, 檔案類型定義: FILE *words; words=fopen(argv[1],”r”);
上面這兩句也可以在定義時直接賦值:FILE *words=fopen(argv[1],”r”);
fgets(word, 100, words); 這個函數用來讀取一個文字檔內容,其中word為一個數組用來接收資料,100讀取長度,words為檔案類型.
其傳回值為BOOL型,讀取檔案時,遇到分行符號自動結束本次讀取,並且將檔案的位置標誌置於下行開始.
可以用這個語句將讀取的內容轉為字串:word[strlen(word)-1]=‘\0’; 反斜線0是空操作字元用來表示字串結束.
檔案標準路徑的寫法:/Users/Murphy/…
每一個使用者,均有以使用者名稱命名的根目錄檔案夾結構,其對應的系統檔案夾路徑如下:
公用:/Users/使用者名稱/Public
圖片:/Users/使用者名稱/Pictures
文稿:/Users/使用者名稱/Documents
5,類與對象的使用
1> 類的定義,可以分為兩個部分,一個部分是聲明部分,一個部分是闡述部分:
//聲明部分用來描述定義各個成員和方法,格式如下:
@interface 類名 :基類名 //這裡基類名可以使用NSObject, 或者其他基類。
{
@public/@private/@protected //其實Obj-c並不存在真正的私人方法.這是Obj-c的動態本質決定的.
成員定義區;
}
@public/@private/@protect
方法定義區; //方法可以用加號或者減號來對應類方法或者成員方法.如果沒有加減號,則是函數原型.
e.g. -(void) setmember : (類型)參數;
@end
’ //類的聲明部分主要是針對其方法進行的,格式如下:
@implementation 類名
-(void)方法名 : (類型)參數
{
方法實現;
}
@end //類名 在結束符後,添加類名,是一個好的習慣,可以增加程式的可讀性.
這裡注意,方法的傳回值也是需要類型定義的,一定要用加減號(類型)的形式來說明,括弧不能省略.同樣,參數的
類型圓括弧也不能省略.
在@implementation中允許出現無聲明的方法,這種方法可以看做是類私人方法(與Delphi相同).
在@implementation部分的參數名可以不與@interface部分相同.注意,在@implementation中使用的參數
最好不要與@interface部分的成員變數同名,否則會隱藏執行個體變數,並產生警告資訊.
如果想調用隱藏的執行個體變數可以用self->成員名來進行.
2>類和對象的使用文法:
a> 在Obj-c中,所有對象的原基類都是NSObject,(這相當於Delphi中的Object).
b>Obj-c中的所有成員變數的定義,均是 類型名在前,變數名在後.並且在定義的時候就可以直接賦值.
c>Obj-c的中綴符調用方法:
[對象名 方法名: 參數];
這裡方法名和冒號可以看成是一體的,它告訴編譯器後面會出現參數.而在不含參數的方法後面添加冒號會報錯.
d>類的公用介面稱為API(application programming interface)
e>在方法體中,允許使用self來訪問對象本身.
f>NSObject類具有一個類方法new,(相當於Delphi的構造方法).我們可以通過調用這個方法得到一個執行個體.
[類名 new]; // 當然所有類方法,都可以用向類名發送訊息的方法進行調用.
g>id 可以用來定義一個通用物件變數,它可以指向任何對象,並且可以用id 來定義一個數組,然後每個數組元素
都指向不同類的對象. //這裡有個疑問,為什麼不直接用NSObject代替id,不過我好好研究了下,發現id跟Delphi
中引用Object還真是不同,id 定義的對象,你可以直接向它發送各種子類訊息,而不需要用as 進行類轉換.
3>類繼承的實現:
a>Obj-c廢棄了C++多繼承的特性,在Obj-c中是不允許多繼承的.(這點跟Delphi是一樣的).
b>Obj-c在聲明的時候,是沒必要像Delphi那樣用virtual或者dynamic來聲明虛函數的.
只需要在子類覆蓋此方法的時候,在闡述部分使用super關鍵字,即可完成繼承.其調用父類部分格式為:
[super 方法名稱:參數]; //即完成了對父類虛方法的調用,類似Delphi中的inherited; 但是這個語句是寫在覆蓋
函數之外的.
super關鍵字,會沿著超類鏈持續往上級尋找,直到找到父類的方法.
4>類的複合:
將若干個對象組合在一起,並且形成一個新對象的過程就叫複合.
每一個組合子物件都可以看作是母對象的一個屬性,而對每個屬性都可以用同名的getter和setter方法來進行
儲存,一般都是成對出現,其格式如下:
-(子物件類*) 子物件名; //這裡省略掉了對應的get關鍵字,除非getter方法需要用到指標形參才會添加get
-(void) set子物件名:(子物件類型*) new子物件名; //這裡的形參最好不要與原對象同名,
set後跟的對象名,第一個字母一般習慣大寫.
注意,當使用setter方法進行屬性設定時,被替代的資料其實是屬性的指標,而不是真實值.由於Obj-c的對象引用
機制,我們不需要考慮到這裡的主動釋放,這跟Delphi是不同的.
屬性的自我構造,可以使用init函數來實現,在定義屬性類中,用以下語句可以實現屬性對象的自我構造:
注意init方法屬於對象的內部方法,是不需要在@interface部分主動聲明的.
@implementation 母對象名
-(id)init
{
if(self=[super init]){
屬性名稱=[屬性類名 new];
}
return(self);
}//init
…
@end
這樣就形成了屬性的自我構造,不過如果屬性有相應的setter方法,其實不用構造也可以,不過使用時需要主動賦值.
5>標頭檔的拆分,指向,匯入和繼承:
在用.m檔案和.h檔案拆分複合類時,需要在複合類的標頭檔中用 @class 類名 指向其複合的屬性類.
而在複合類的闡述檔案中,不僅僅要用#import匯入其對應標頭檔,也必須用其匯入對應的所有屬性類的標頭檔.
而在衍生類別拆分檔案時,衍生類別的標頭檔,只需要匯入父類的標頭檔就可以(可以完全忽略父類中已有的系統標頭檔)
6>物件導向的設計意義:
a>在物件導向和面向過程的設計中,最大得差別是其功能修改增刪時的改變方式.物件導向可以避免修改到整體
的處理函數,也不需要修改基本的結構體,只需要增加一個類基本就可以適應變化了.
b>面向過程的設計是函數第一,資料第二,這導致程式修改經常會影響到介面;而物件導向的設計,可以直接吧原先
函數修改的部分巧妙的移動到對象的方法之中,我們只需要關注對象這個資料就好了,不會影響到函數和介面.
c>當不同類中出現了大量的重複的代碼,就絕非優良的設計,我們可以更改其類的繼承結構,使這些重複代碼在中間
的繼承類中實現,這種移動和簡化代碼的方法稱為重構.
d>當你建立的新類與現有類是is a 的關係就可以使用繼承;當你建立的類與現有類是has a 的關係,就需要用到複合了.
7>物件導向的術語:
a>超類:superclass
b>父類:parentclass,同超類.
c>子類(衍生類別):subclass
d>孩子類:childclass,同子類.
6,常用的XCode操作技巧
1>花+[ 和 花+]可以將選定得代碼塊左移或者右移
2>ESC鍵可以關閉和開啟自動完成的選擇框.
3>Control+/ 可以在輸入時自動跳在預留位置上.
4>花+Control+S可以建立一個快照.
5>花+Shift+O 快速開啟一個單元檔案.
6>Control+F/B 分別是前移游標和後移游標.
7>Control+P/N 分別是上移游標和下移游標.
8>Control+A/E 分別是移動游標到該行的行首和行尾.
9>Control+T 把游標前的字元往後拖一個位置.
10>Control+D 刪除游標右邊的字元(相當於windows中的Del鍵).
11>Control+K 刪除一行.其實這個是刪除當前行游標後面的部分.
12>Control+L 調整視窗,以便將當前的游標居於視窗中心.
13>花+Y 以調試方式運行程式.
14>花+Option+P/O/I/T 分別是調試的 繼續,跳過,跳入,跳出.
Xcode及obj-c的基礎知識