1. OC語法

總結

  • 結構體內存對齊: 結構體內存的大小必須是最大成員內存大小的倍數
  • 操作系統有分配內存對齊的概念(Bucket Size), 大都以16個字節爲單位對齊
  • 在iOS堆空間中分配內存的話都是16的倍數,也就是說iOS堆內存中最小內存的大小爲16, 這樣對於操作系統訪問CPU是最優最快的。(如果結構體的成員變量只需要24個字節就夠用,而iOS中分配堆內存大小是32個字節)
  • class_getInstanceSize( )返回某個類對象至少需要多少空間
  • malloc_size()返回的是實例對象實際分配的內存空間

一、面向對象

1.1 Objective-C的本質

  • 我們平時編寫的Objective-C代碼,底層實現其實都是C\C++代碼
    在這裏插入圖片描述

  • 所以Objective-C的面向對象都是基於C\C++的數據結構實現的

  • 思考:Objective-C的對象、類主要是基於C\C++的什麼數據結構實現的?

    • 結構體
  • 將Objective-C代碼轉換爲C\C++代碼

    xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 輸出的CPP文件 
    
    • 如果需要鏈接其他框架,使用-framework參數。比如-framework UIKit

1.2 OC對象的本質

  • 思考:一個OC對象在內存中是如何佈局的?
  • NSObject的底層實現在這裏插入圖片描述
  • 一個普通類的底層實現
    在這裏插入圖片描述
    在這裏插入圖片描述
  • 思考:一個Person對象、一個Student對象佔用多少內存空間?
    在這裏插入圖片描述

1.3 實時查看內存數據

  • Debug -> Debug Workfllow -> View Memory (Shift + Command + M)
  • 也可以使用LLDB指令
    在這裏插入圖片描述

1.4 2個容易混淆的函數

  • 創建一個實例對象,至少需要多少內存?
#import <objc/runtime.h>
class_getInstanceSize([NSObject class]);
  • 創建一個實例對象,實際上分配了多少內存?
#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);

二、常用LLDB指令

  • print、p : 打印

  • po : 打印對象

  • 讀取內存

memory read/數量格式字節數 內存地址 
x/數量格式字節數 內存地址
x/3xw 0x10010
  • 修改內存中的值
memory write 內存地址 數值 
memory write 0x0000010 10
  • 格式

    • x是16進制,f是浮點,d是10進制
  • 字節大小

    • b : byte 1字節,
    • h : half word 2字節
    • w : word 4字節,
    • g : giant word 8字節

三、OC對象的分類

  • Objective-C中的對象,簡稱OC對象,主要可以分爲3種
    • instance對象(實例對象)
    • class對象(類對象)
    • meta-class對象(元類對象)

3.1 instance

  • instance對象就是通過類alloc出來的對象,每次調用alloc都會產生新的instance對象
NSObject *object1 = [[NSObject alloc] init];
NSObject *object2 = [[NSObject alloc] init];
  • object1、object2是NSObject的instance對象(實例對象)

  • 它們是不同的兩個對象,分別佔據着兩塊不同的內存

  • instance對象在內存中存儲的信息包括

    • isa指針
    • 其他成員變量
  • Person對象

@interface MJPerson : NSObject {
	@public
    int _age;
}
@end
  • Person對象使用
MJPerson *p1 = [[MJPerson alloc] init];
p1->_age = 3;

MJPerson *p2 = [[MJPerson alloc] init];
p2->_age = 4;

在這裏插入圖片描述

3.2 class

  • objectClass1 ~ objectClass5都是NSObject的class對象(類對象)
  • 它們是同一個對象。每個類在內存中有且只有一個class對象
ClassobjectClass1 = [object1 class];
Class objectClass2 = [object2 class];
Class objectClass3 = object_getClass(object1); // Runtime API
Class objectClass4 = object_getClass(object2); // Runtime API
Class objectClass5 = [NSObject class];
  • class對象在內存中存儲的信息主要包括
    • isa指針
    • superclass指針
    • 類的屬性信息(@property)、類的對象方法信息(instance method)
    • 類的協議信息(protocol)、類的成員變量信息(ivar)

    • 在這裏插入圖片描述

3.3 meta-class

Class objectMetaClass = object_getClass(objectClass5);
  • objectMetaClass是NSObject的meta-class對象(元類對象)

  • 每個類在內存中有且只有一個meta-class對象

  • meta-class對象和class對象的內存結構是一樣的,但是用途不一樣,在內存中存儲的信息主要包括

    • isa指針
    • superclass指針
    • 類的類方法信息(class method)

    • 在這裏插入圖片描述

3.4 注意

  • 以下代碼獲取的objectClass是class對象,並不是meta-class對象
Class objectMetaClass2 = [[[NSObject class] class] class];

3.5 查看Class是否爲meta-class

#import <objc/runtime.h>

BOOL result = class_isMetaClass([NSObject class]);

四、isa 和 superclass

4.1 isa指針

在這裏插入圖片描述

  • instance的isa指向class

    • 當調用對象方法時,通過instance的isa找到class,最後找到對象方法的實現進行調用
  • class的isa指向meta-class

    • 當調用類方法時,通過class的isa找到meta-class,最後找到類方法的實現進行調用

4.2 class對象的superclass指針

在這裏插入圖片描述

  • 當Student的instance對象要調用Person的對象方法時
    • 會先通過isa找到Student的class
    • 然後通過superclass找到Person 的class
    • 最後找到對象方法的實現進行調用

4.3 isa、superclass總結

  • instance的isa指向class

  • class的isa指向meta-class

  • meta-class的isa指向基類的meta-class

  • class的superclass指向父類的class p 如果沒有父類,superclass指針爲nil

  • meta-class的superclass指向父類的meta-class p 基類的meta-class的superclass指向基類的class

  • instance調用對象方法的軌跡

    • isa找到class,方法不存在,就通過superclass找父類
  • class調用類方法的軌跡

    • isa找meta-class,方法不存在,就通過superclass找父類

在這裏插入圖片描述

五、Class的結構

5.1 isa指針

  • 從64bit開始,isa需要進行一次位運算,才能計算出真實地址
    在這裏插入圖片描述
    在這裏插入圖片描述

5.2 objc4源碼下載

5.3 窺探struct objc_class的結構

  • class、meta-class對象的本質結構都是struct objc_class
    在這裏插入圖片描述
    在這裏插入圖片描述

5.4 objc_getClass和object_getClass的區別

  1. Class objc_getClass(const char *aClassName)
    1> 傳入字符串類名
    2> 返回對應的類對象

  2. Class object_getClass(id obj)
    1> 傳入的obj可能是instance對象、class對象、meta-class對象
    2> 返回值

    • a) 如果是instance對象,返回class對象
    • b) 如果是class對象,返回meta-class對象
    • c) 如果是meta-class對象,返回NSObject(基類)的meta-class對象
  3. - (Class)class、+ (Class)class
    1> 返回的就是類對象

- (Class) {
    return self->isa;
}

+ (Class) {
    return self;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章