OC 基礎入門
OC 源檔案
OC 源檔案為 .h 和 .m( m表示 message,表示 OC 中的消息機制 )
在 .m 檔案中可以寫 OC 代碼、C 代碼、C++ 代碼。反正 Java 的 .class 檔案不能寫 C 和 C ++。
NS 字首
從之前的 OC 的曆史中知道 OC 來自 NextStep. 是以許多的 OC 的類都是帶了 NS 字首。
注釋
OC 的注釋和 Java 一樣分為兩種:
單行注釋:
// 我是單行注釋
多行注釋
/*
*我是多行注釋
*/
@符号
在 OC 中大多數的關鍵字是用 @ 符号開頭的。并且字元串類型是以 @ 開頭申明的。
main 函數
這一點是和 Java 一緻,程式的入口也是 main 方法。
OC 的 main 函數是可以不帶參數。寫法如下:
帶參
int main(int argc,const char * argv[]){
NSLog(@"Hello World!");
}
不帶參
int main(){
NSLog(@"Hello World!");
}
Java 語言的 main 函數
public static void main(String [] args){
println("Hello World!");
}
OC 基本資料結構
OC 語言包含了 C 所有的資料結構,并且有更多其他的資料結構。
C:
- int float double char
- int的修飾符
- short、long、 long long
- unsigned 、signed
- ...
OC:
- CGFloat、BOOL、NSInteger
其中 BOOL 是的取值為 YES/ON 對應就是 Java true/false.
CGFloat 和 NSInteger 是為了相容 64 位計算機和 32 位計算機而存在的,在 32 位作業系統中,CGFloat 表示的就是 4 個位元組的 float,而在 64 位作業系統中,CGFloat 表示的是 8 個位元組的 double.
NSInteger 也是類似的 —— 32 位作業系統中為 4 個位元組 int. 64 位作業系統中為 8 個位元組 long。
OC 也是有 Boolean 存在的。Boolean 表示的值就是 TRUE/FALSE 對應就是 Java true/false
BOOL 本質:
typedef signed char BOOL;
#define YES ((BOOL)1)
#define NO ((BOOL)0)
Boolean 本質:
typedef unsigned char Boolean;
#define true 1
#define false 0
本質差別是 Boolean 定義的是枚舉。BOOL 定義的是宏。
OC 的資料類型
- id 類型:萬能指針,可以指向任何的 OC 對象。其實質是編譯時不檢測,運作時檢測。
- class - 表示類
- SEL: 方法選擇器
- nil:nil 類似是 NULL 但是 nil 是一個對象
- block : 表示一個代碼塊
OC 的文法知識其實有蠻多,以下知識基礎的一部分.
目錄部分:
文章目錄
@ 符号
在 OC 語言中,絕大部分的關鍵字使用的 @ 符号開頭。記住這是一個規則就好了。
字元串
在 Java 中字元串和 C 語言中字元串定義的方式是一樣的。
但是在 OC 中的字元串的定義是需要添加 @ 的,在OC 中字元串類型使用的是 NSString ,相對而言添加一個 NS 字首。
Java: "Android" "Java"
OC: @"OC" @"iOS"
//比如定義一個變量
NSString *name = @"小明";
NSLog 日志輸出
OC 中的日志輸出對象為 NSLog.
文法:NSLog(字元串); —— 表示需要列印的日志。
Java 中的 Log 和這個對标的,但是目前還沒有發現 NSLog 有和 Log 日志等級關系的定義。
//簡單使用
NSLog(@"Hello world, OC");
//進階使用
NSLog(@"1+1=%d",2)
#import導入指令
“#”表示的是一個預處理指令。
這個指令的作用:将檔案的内容在預編譯的時候拷貝寫指令的地方.
簡單的原理:#import指令在包含檔案的時候,底層會先判斷這個檔案是否被包含 如果被包含就會略過 否則才會包含.
//導入系統的相關的使用的是“<>”
#import <Foundation/Foundation.h>
//導入其他非系統的類或者頭檔案使用的是 ""
#import "Person.h"
類
什麼是一個類
面向對象語言定義基本上都是一樣,這個定義 Java 和 OC 基本上沒差。
描述具有相同特征和行為事物的集合。
OC 怎麼建立一個類
OC 的類通常是有兩個檔案,一個是 .h 檔案,一個是.m 檔案
.h 頭檔案
表示一個類的聲明
文法格式:
@interface 類名 : NSObject
{
聲明特征(變量)
}
-聲明方法
@end
說明
- interface 在 Java 中表示的是接口的意思,但是在 OC 表示的是頭檔案的辨別。
- @end 作為表示目前這個類聲明完成。
- “ :” 表示繼承的關系,和 Kotlin 有點類似。
- NSObject 和 Java 是一樣的,所有的對象建立時會預設自動生産一個這樣的繼承關系,Java 是不需要顯示出來的,但是 OC 會顯示出來。
@interface Person : NSObject
{
int age;
NSString *name;
BOOL isBoy;
}
@end
.m 實作檔案
表示一個類的實作
文法定義
@implementation 類名
{
特征和變量
}
方法實作
@end
注意事項:
- 在 .m 檔案中定義的變量為私有變量,在其他的類是不能調用到的。
- 在 .m 中定義的方法在 .h 檔案中如果沒有定義就不能被外部的類所調用。
- 如果在 .h 檔案中聲明了一個方法,但是在 .m 檔案中沒有實作這個類,可編譯通過,不可以運作。
@implementation Person
{
//錢肯定隻有自己能夠通路
float money;
}
@end
與 Java 語言相比,類的定義在 OC 中顯得略有麻煩。
類生成對象的方式
類生成對象在 OC 有好幾種常見的方式,這裡隻闡述兩種比較常用的方式:
//第一種:
Person *person = [Person new];
//第二種
Person *person = [[Person alloc] init];
其中 alloc 表示配置設定記憶體空間, init 表示初始化成員變量。
這兩種方式完全等價。
變量
文法
在 @interface 中定義的變量是在 { } 中,并且需要在變量頭部聲明 @public 才可以在 .m 和作為對象調用。
在 @implementation 中定義的文法隻能在 .m 中使用。
代碼
.h 中:
@interface Person : NSObject
{
@public // 聲明這些變量可以被通路
int _age;
NSString *_name;
BOOL _isBoy;
}
@end
.m 中:
@implementation Person
{
//錢肯定隻有自己可以通路了
int moeny;
}
@end
調用
//這個是和 C 語言相容過來的。
Person *person = [Person new];
person->_name = 3;
方法
調用角度分為兩種:一種是類方法;一種是對象方法。
這個地方對标的是 Java 中的靜态方法和類方法。
從方法本身定義出發,也是分為兩種:一種是無參方法和有參方法。
和所有其他的程式語言一樣。
方法的構成的要素:(與語言無關)
- 傳回類型
- 方法名稱
- 參數(可有可無)
無參對象方法
文法
-(傳回類型)方法名稱;
這個文法和 Java 的差異還是蠻大的。
方法申明:
@interface Person : NSObject
{
int age;
NSString *name;
BOOL isBoy;
}
- (void) eat;
@end
方法實作:
@implementation Person
{
//錢肯定隻有自己能夠通路
float money;
}
@end
- (void) eat{
NSLog(@"人是鐵飯是鋼");
}
調用方法
[對象 方法名]
Java 中的都是點文法 ,但是在 OC 中不是這樣。
//Java對象方法調用(Java 中不存在類對象的概念,隻是為了區分是以此處表示為對象方法)
Person mPerson = new Person;
mPerson.eat();
//OC 中對象方法調用
Person *person = [Person new] ;// OC 生成對象的方式
[person eat];
有參對象方法
文法
-(傳回值類型)方法名稱:(參數類型)參數名稱1 : (參數類型)參數名稱2
方法名稱和參數數值之間以 “:” 表示分隔。
方法申明:
@interface Person : NSObject
{
@public // 聲明這些變量可以被通路
int _age;
NSString *_name;
BOOL _isBoy;
}
//無參
-(void)eat;
//有參
-(void)setName:(NSString *)name withAge:(int)age withIsBoy:(BOOL)isBoy;
@end
方法實作:
@implementation Person
{
//錢肯定隻有自己可以通路了
int moeny;
}
-(void)eat{
NSLog(@"人是鐵飯是鋼");
}
/*setName withAge withBoy withIsBoy 這個整體就是一個方法名稱,至于為
*什麼用 withXXX 這是 OC 書寫的一種比較好的習慣吧。這些變量之間沒有特殊的符号的定義,除了變量空格就好了。
*/
-(void)setName:(NSString *)name withAge:(int)age withIsBoy:(BOOL)isBoy{
_name = name;
_age = age;
_isBoy = isBoy;
}
@end
調用方式
這就不用相關的語言描述了。直接上代碼:
Person *person = [Person new];
// 一個叫小明,3歲的男孩。
[person setName:@"小明" withAge:3 withIsBoy:YES];
以上基本就是對象方法的全部了
類方法
對象的方法用 “-” 表示。類方法用 “+” 表示。其他的方式全部和對象方法一緻。
文法上展現的很簡單。
在 OC 中類方法不能通路屬性。是以一般如果在一個方法中不需要用到類屬性的關系就可以使用類方法,相比而言,類方法的有:
- 節約空間:不需要生成對象就可以調用方法
-
提高效率:可以直接通過類通路方法
方法聲明:
@interface Utils: NSObject
//無參方法
+ (void)start;
//計算和(有參方法)
+(int)add:(int)num1 andNum2:(int)num2;
@end
方法實作:
@implementation Utils
+ (void)start{
NSLog(@"開始啦....");
}
+ (int)add:(int)num1 andNum2:(int)num2{
return num1 + num2;
}
@end
方法調用:
//類方法調用無參方法
[Utils start];
//類方法調用有參方法
[Utils add: 1 andNum2: 2 ];
分組導航标記
在 OC 中有一種特殊文法,可以給相關方法分區。
Java 中可能有這樣操作。但是我是不知道,XCode 中支援相關方法的預覽。比如說所有的點選事件的響應可以分類為 View Action。UI 可以分為 initView。
文法規則
#pragma mark - 分組名稱
如下圖示說明:
效果圖示
nil 與 NULL 的差異
在 Java 中 null 表示一個空對象。在 OC 中有 nil 和 NULL 兩種方式,其中 NULL 屬于 C 的定義。
NULL:表示這個定義沒有指向任何記憶體的空間。
nil: 表示這個定義沒有指向任何對象。
因為 OC 是面向對象的語言,是以一般建議使用 nil 來表示一個對象沒有被指派。
簡單的 OC 運作時記憶體區域劃分
區域 | 定義 |
---|---|
堆 | 存儲臨時變量 |
棧 | 存儲成員變量,通過 new 或者 alloc 申請出來的空間 |
BSS段 | 存儲未初始化的全局變量,比如靜态變量 |
資料段 | 存儲已經初始化的全局變量,比如常量 |
代碼段 | 存儲代碼,存儲程式的代碼 |
加載類
和 Java 一樣,OC 中代碼也是有類加載的概念,這個對于我們來說還是蠻好了解的 ,程式沒有運作時,代碼是儲存在實體記憶體中,程式運作時肯定需要一家代碼的加載的過程,加載最小的單元就是類,那麼加載類的過程就是加載類了。
好像寫的有點啰嗦了。
類對象
在 Java 中,我查過一些資料,沒有類對象的概念,這個概念應該是 OC 語言獨有的概念了。
類加載完成之後就是就會生成一個類對象。類對象的生命周期和程式的生命周期都是一樣的。
OC 的類對象其實是這樣的,比如一個類加載成類對象以後,如果下一次去生成一個對象的時候,直接用類對象生成,不需要再去進行類加載的操作。
類對象會加載會加載方法到代碼去,因為我們在操作一個執行個體對象的時候,是在操作他的相關變量。而其中對應的方法實作一直都是一樣的,那麼就不需要重複加載,浪費空間和時間。在 OC 中執行個體對象隻會包含類對象的引用。可以去看一下運作的代碼很看到一個 isA 的引用,這個就是類對象的引用。
對象生成的過程
宏觀來看,OC 執行個體對象的生成和 Java 執行個體對象的初始化過程差不多,都是申請記憶體,然後初始化變量。
1). Person *p1; 會在棧記憶體中申請1塊空間. 在棧記憶體中聲明1個Person類型的指針變量p1。
p1是1個指針變量. 那麼隻能存儲位址.
2). [Person new]; 真正在記憶體中建立對象的其實是這句代碼.
new做的事情
A. 在堆記憶體中申請1塊合适大小的空間.
B. 在這個空間中根據類的模闆建立對象.
類模闆中定義了什麼屬性.就把這些屬性依次的聲明在對象之中.
對象中還有另外1個屬性 叫做isa 是1個指針. 指向對象所屬的類在代碼段中的位址.
C. 初始化對象的屬性
如果屬性的類型是基本資料類型 那麼就指派為0
如果屬性的類型是C語言的指針類型 那麼就指派為NULL
如果屬性的類型是OC的類指針類型 那麼就指派為nil
D. 傳回對象的位址.
其中執行個體對象隻有屬性沒有方法,至于原因上面已經說明白了。
屬性的預設值
預設值和 Java 基本一樣,如下:
- 如果屬性的類型是基本資料類型 預設值是0(BOOL 是 false )
- 如果屬性的類型是C指針類型 那麼預設值是NULL
- 如果屬性的類型是OC指針類型 那麼預設值是nil