import、#include和@class有什麼區別
、相互引用標頭檔案問題

LeeJTom發表於2018-03-19

import、#include和@class有什麼區別

  1. #import是Objective-C匯入標頭檔案的關鍵字
    • import會包含這個類的所有資訊,包括實體變數和方法
    • 使用#import標頭檔案會自動只匯入一次,不會重複匯入,相當於#include和#pragma once
  2. #include是C/C++匯入標頭檔案的關鍵字
  3. @class告訴編譯器某個類的宣告,當執行時,才去檢視類的實現檔案,可以解決標頭檔案的相互包含

    @class只是告訴編譯器,其後面宣告的名稱是類的名稱。

  4. #import<>用來匯入系統的標頭檔案,#import“”用來匯入使用者的標頭檔案。

相互引用標頭檔案問題

  • 如果有迴圈依賴關係,如:A–>B, B–>A這樣的相互依賴關係。
    • 首先,兩個.m檔案互相引用.h檔案,不會出現問題的。
    • 但是比如在.h裡的某個屬性,型別是自定義的類,這時候如果只在.m裡引用就編不過了。
//  JTTest1.h
#import <Foundation/Foundation.h>
#import "JTTest2.h"

@interface JTTest1 : NSObject
@property (nonatomic, strong) JTTest2 *test; //!!報錯“Unknown type name 'JTTest2'; did you mean 'JTTest1'?”

@end


//  JTTest2.h
#import <Foundation/Foundation.h>
#import "JTTest1.h"

@interface JTTest2 : NSObject

@end

複製程式碼
  • 解決:
    使用@class。在.h檔案中使用@class,然後在.m檔案中#import "JTTest2.h"即可。
//  JTTest1.h
#import <Foundation/Foundation.h>
@class JTTest2;

@interface JTTest1 : NSObject
@property (nonatomic, strong) JTTest2 *test; 
@end


//  JTTest1.m
#import "JTTest1.h"
#import "JTTest2.h"
@implementation JTTest1

@end
複製程式碼
  • 原因: @class JTTest2;這句話的意思就是,告訴編譯器,確實有JTTest2這個類,具體細節你不用管,別報錯就行了。所以顯然,到了.m裡,它只知道有這個類,卻不知道這個類有什麼屬性,有哪些方法。所以需要在.mimport這個標頭檔案。

儘量在.m而不是.h裡使用import引用

所以我們推薦儘量在.m裡引用標頭檔案,而不是在.h裡,必要時使用@class

在編譯效率方面考慮,如果你有100個標頭檔案都#import了同一個標頭檔案,或者這些檔案是依次引用的,如A–>B, B–>C, C–>D這樣的引用關係。當最開始的那個標頭檔案有變化的話,後面所有引用它的類都需要重新編譯,如果你的類有很多的話,這將耗費大量的時間。而是用@class則不會。

但是也有一些情況,是不可避免要在.h裡引用的。比如:繼承某個類,必須在.himport 父類的.h;類實現某個介面,必須在.h裡引用介面的.h等等。

相關文章