對象在內存中的存儲
1. 內存中的五大區域.
棧: 存儲局部變量.
堆: 允許程序員手動在堆區申請指定的連續的字節數的空間來使用.
BSS段: 存儲未初始化的全局變量、靜態變量.
數據段(常量區): 存儲已經初始化的全局變量、靜態變量、常量數據.
代碼段:存儲程序的代碼.
2. 類加載.
1). 當創建對象的時候,肯定需要訪問這個類.因為只有訪問了類才知道類中有那些成員.
2). 如果只是聲明類指針的時候,也會訪問這個類.以確定這個類型是否存在.
當類第一次被訪問的時候,會將類存儲到代碼段之中. 這個過程叫做類加載.
將類的代碼存儲在代碼之中.
將類的代碼以字符串的形式存儲在代碼段中.
只有類第1次被訪問的時候,才會有類加載.
一旦類被加載到代碼區.直到程序結束的時候才會被回收.
3.對象在內存中是如何存儲的.
1). 類的本質是:自定義的數據類型.
HMPerson *p1 = [HMPerson new];
2). HMPerson *p1;
這句話,僅僅是聲明了1個指針變量而已.這個指針變量的類型是HMPerson*.
p1是1個局部的變量.所以p1指針變量是存儲在棧區的.
p1是1個指針變量,所以這個變量中只能存儲地址.
本質上來講.p1是1個指針變量 不是1個對象.
3).[HMPerson new];
這句話,才是在真正的創建對象.
new做的事情.
a. 在堆內存中申請一塊合適大小的空間.
b. 在申請的這塊空間中根據類的模板創建對象.
類中有哪些屬性.就把類的屬性依次的挨個的一個不落的聲明在這個對象中.
對象中除了有類中定義的屬性之外,還有1個屬性叫做isa 這是1個指針.
這個isa指針指向代碼段中的類.
c. 初始化對象的屬性.為對象的屬性賦默認值
-> 如果屬性的類型是基本數據類型.就賦值為0
-> 如果屬性的類型是C指針類型.就賦值為NULL
-> 如果屬性的類型是OC指針類型.就賦值為nil
d. 返回這個對象在堆空間中的地址.
將這個地址賦值給p1指針.
p1指針指向了堆空間中的HMPerson對象.
4). 注意
a. 對象中只有類的屬性+isa的指針. 沒有方法.
isa指針指向了代碼段中的類.
b. 如何訪問對象的屬性.
通過指針就可以找到指針指向的對象.找到對象了,就可以找到對象的屬性.
p1->_name = @"jack";
c. 如何調用對象的方法?
[p1 sayHi];
通過p1指針找到對象,發現是在調用方法.那么再根據對象的isa指針找到代碼段中的類.
再找到類中的對應的方法來執行.
d. 為什么方法不保存在對象中.
因為不管對象有多少個.方法的代碼都是一樣的.沒有必要保存多份,只保存1份就可以了.
e. 相同類的對象的isa指針的值一定都是一樣的.
4. 對象的屬性的初始值.
創建1個對象 如果沒有為這個對象的屬性賦值.那么這個對象的屬性是有值的.
屬性的類型是基本數據類型: 0
OC指針: nil
C指針: NULL
Nil
1. C語言中學習的NULL.
a). NULL是1個值. 是C語言中指針變量的值.
b). 如果1個指針的值為NULL值,就代表這個指針不指向內存中的任何空間.
c). NULL本質上是1個宏.
define NULL ((void*)0)
所以 NULL 和 0 等價.
2. nil
a). nil也是1個值. 它也是1個指針變量的值.
b). nil的本質也是1個宏.
#define __DARWIN_NULL ((void *)0)
所以,nil和NULL完全是等價的.
c). 所以,如果
想要讓1個指針不指向任何空間.
可以為這個指針變量賦值為NULL nil 0
3. 使用建議
a). 如果希望C指針不指向任何空間.一般為其賦值為NULL
b). 如果希望OC指針不指向任何空間,一般賦值nil
4. 注意問題
如果1個類指針的值為nil
HMPerson *p1 = nil;
代表p1指針不指向任何對象.
1). 所以這個時候 通過p1去訪問p1指向的對象的屬性的時候,肯定的會報錯.
對象都沒有 哪里來的屬性呢?
2). 這個時候, 通過這個指針去調用方法的時候,
不會報錯.也不會崩潰.
只是沒有任何反應的啦.
分組導航標記
1. 一種快速的方式查找文件中的代碼.
Xcode 提供了導航條可以快速查找.
2. 分組導航標記.
1). #pragma mark 標記名.
2). #pragma mark - 就會產生1條分割線.
3). #pragma mark - 標記名. 就會產生1條分割線.並取1個標記名.
方法與函數
1. 之前在C語言中叫做函數.
void test();
在OC類中定義的叫做方法.
- (void)sayHi;
2. 相同點:
1). 都封裝1段代碼,都表示1個相對獨立的功能.
2). 函數/方法 如果不被調用,那么其中的代碼是不會被執行.
3. 不同點.
1). 語法不同.
2). 定義的位置不一樣.
a. 函數除了函數的內部和@interface的大括弧中不能定義.其他的地方都是可以定義的.
b. 而方法的聲明只能在@interface的大括弧的外面,實現只能在@implementation中.
就算把函數寫在類中,這個函數也不是屬於這個類的.
3). 歸屬感不同.
a, 函數就像是1個沒有家的孩子,每1個函數是孤立的.]
b. 方法是屬於類的.類就是方法的家.
4). 調用形式不同.
a. 函數直接調用.
b. 方法必須要通過對象名來調用.