一、搜索路徑設置
$(SRCROOT)
宏和$(PROJECT_DIR)
宏都指xxx.xcodeproj所在的目錄
$(default)
代替 /Users/xxx/Library/Developer/Xcode/DerivedData/xxxxx-erpfssifaoxedbccegoqjiclrfds ,這個路徑受 xcode->Preferences->locations
影響混槐。本文只討論默認情況這種轩性。
$(SYMROOT)
= $(default)/Build
$(BUILD_ROOT)
、$(BUILD_DIR)
= $(SYMROOT)/products
= $(default)/Build/products
$(CONFIGURATION)
當前的Build configuration悯嗓,Debug時值為Debug卸察。
$(EFFECTIVE_PLATFORM_NAME)
當前平臺的名字,模似器時為值為-iphonesimulator
合武,當為真機時為-iphoneos
$(CONFIGURATION_BUILD_DIR)
= $(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
= $(default)/Build/products/Debug-iphoneos
(Build configuration為debug,平臺為真機情況)
在編譯時盟庞,編譯器會將相對路徑替換成絕對路徑汤善,因此,頭文件絕對路徑=搜索路徑+相對路徑卸伞。
Framework Search Paths
:框架文件搜索路徑設置(.framework文件)
Header Search Paths
:頭文件搜索路徑設置(.h文件)
Library Search Paths
:庫搜索路徑設置(靜態(tài)庫.a文件)
Header Search Paths
設置系統(tǒng)目錄空間頭文件(.h文件)搜索路徑荤傲。
例如:引用工程中颈渊,路徑為:xxx/testDemo/scr/test.h 的頭文件,目錄結構如下:
如果在Header Search Paths
中添加$(SRCROOT)
雾家,則引用頭文件時绍豁,需要寫為#include "scr/test.h"
如果在Header Search Paths
中添加$(SRCROOT)/scr
,那么頭文件引用直接引用 #include "test.h"
System Header Search Paths
和Header Search Paths
基本一樣竹揍,區(qū)別只在于Header Search Paths
以一種抑制系統(tǒng)搜索路徑中找到的標頭的大多數(shù)警告的方式傳遞給編譯器。
This setting is very similar to "Header Search Paths", except that headers are passed to the compiler in a way that suppresses most warnings for headers found in system search paths.
所以通常使用Header Search Paths
來設置无拗,下文也忽略這個設置昧碉。
User Header Search Paths
設置用戶目錄空間頭文件(.h文件)搜索路徑。
和Header Search Paths
的區(qū)別如下:
當import時, 有兩種方式:
#import <SomeClass.h>
#import "SomeClass.h"
在Header Search Paths中設置SomeClass的路徑
我們知道四康,在C語言中锹漱,使用尖括號引用,預處理器會從系統(tǒng)目錄空間(對應Header Search Paths)中搜索文件毕泌,所以此時可以正確引用到。同樣挠说,使用雙引號引用愿题,預處理器會先從用戶目錄空間(對應 User Header Search Paths)搜索,如果沒有找到杆兵,再從系統(tǒng)目錄空間(對應Header Search Paths)中搜索文件仔夺,所以也可以正確正確引用到。在User Header Search Paths中設置SomeClass的路徑
使用尖括號引用就會報錯日裙,因為找不到對應的頭文件惰蜜。使用雙引號則可以正常引用。原理同上格侯。
所以樟结,當需要設置頭文件引用路徑的時候,不推薦設置這里,推薦設置Header Search Paths
驮履。
Always Search User Paths
設置是否總是搜索用戶目錄空間廉嚼,如果設置為YES,則上文中的例子恐似,在User Header Search Paths中設置SomeClass的路徑傍念,也可以使用#import <SomeClass.h>
這種方式引用葛闷。這個設置已被棄用淑趾,不推薦設置忧陪。
Framework Search Paths
設置框架文件(.framework文件)搜索路徑
需要在Framework Search Paths
中添加對應framework所在目錄的路徑,引用時延蟹,需要寫為#include <aaa/aaa.h>
這里需要注意叶堆,設置了Framework Search Paths
,僅僅是在編譯的時候可以找到對應的頭文件俯萌,具體是否將framework鏈接進當前target咐熙,還需要看是否設置Link Binary With Library 或 對應的Other Linker Flags
Library Search Paths
設置靜態(tài)庫(.a文件)搜索路徑
這里需要注意辨萍,設置了Library Search Paths
,就會導致當前靜態(tài)庫被鏈接進當前target
二爪飘、模塊化導入(語義導入)
也就是所謂的@import aaa;
模塊化導入具體有什么優(yōu)缺點拉背,網(wǎng)上一堆資料,同學們可以自行百度犁罩,這里引用了一段stackoverflow上的回答
It's a new feature called Modules or "semantic import". There's more info in the WWDC 2013 videos for Session 205 and 404. It's kind of a better implementation of the pre-compiled headers. You can use modules with any of the system frameworks in iOS 7 and Mavericks. Modules are a packaging together of the framework executable and its headers and are touted as being safer and more efficient than
#import
.
One of the big advantages of using@import
is that you don't need to add the framework in the project settings, it's done automatically. That means that you can skip the step where you click the plus button and search for the framework (golden toolbox), then move it to the "Frameworks" group. It will save many developers from the cryptic "Linker error" messages.
You don't actually need to use the@import
keyword. If you opt-in to using modules, all#import
and#include
directives are mapped to use@import
automatically. That means that you don't have to change your source code (or the source code of libraries that you download from elsewhere). Supposedly using modules improves the build performance too, especially if you haven't been using PCHs well or if your project has many small source files.
Modules are pre-built for most Apple frameworks (UIKit, MapKit, GameKit, etc). You can use them with frameworks you create yourself: they are created automatically if you create a Swift framework in Xcode, and you can manually create a ".modulemap" file yourself for any Apple or 3rd-party library.
這里主要說下床估,怎么設置自己的庫可以被語義導入丐巫。
在XCode的build setting內(nèi),Packaging內(nèi)有以下設置module map的選項
Defines Module (DEFINES_MODULE) :
如果設置為YES,會認為項目自定義自己的組件,允許項目通過組件的方式引入Module Map File (MODULEMAP_FILE)
用來管理LLVM的module map,定義編譯器組件結構.如果defines module為YES的時候,如果Module Map File沒填,會自動生成.
在Cocoapod中递胧,我們可以在podfile內(nèi)添加use_modular_headers!
允許所有pod語義導入.也可以通過:modular_headers => true
配置特定的pod.
三谓着、頭文件引用方式總結
iOS中頭文件,有5種引用方式
#import "aaa.h"
#import "aaa/aaa.h"
#import <aaa.h>
#import <aaa/aaa.h>
@import aaa;
#import "aaa.h"
這種引用方式治筒,可以引用到的頭文件舷蒲,有3種。
-
Header Search Paths
中對應目錄的文件堤框。 -
User Header Search Paths
中對應目錄的文件纵柿。 - 當前project中包含的頭文件,也即
project.pbxproj
文件中包含的頭文件沟使。
#import "aaa/aaa.h"
這種引用方式渊跋,可以引用到的頭文件,只有2種燕少。
-
Header Search Paths
中對應目錄的文件蒿囤。 -
User Header Search Paths
中對應目錄的文件。
#import <aaa.h>
這種引用方式镶摘,可以只可以引用到 Header Search Paths
中對應目錄的文件岳守。
#import <aaa/aaa.h>
這種引用方式湿痢,可以引用到的頭文件
-
Header Search Paths
中對應目錄的文件。 -
Framework Search Paths
中拒逮,對應framework的頭文件 - 上文中臀规,通過語義導入的模塊,使用這種方式玩徊,Xcode可以自動解析為語義導入恩袱,其他方式不行胶哲。
@import aaa;
這種引用方式畔塔,只可以引用到開啟了模塊導入的模塊,即Defines Module設置為YES的庫澈吨,如果沒有開啟模塊導入谅辣,則會報錯冰肴。
綜合上述5中情況,我們可以看出熙尉,#import <aaa/aaa.h>
和#import "aaa.h"
這兩種情況,是更優(yōu)的選擇包归。
結合Cocoapods來看公壤,一般來說,當我們使用Cocoapod的時候厦幅,Cocoapod會自動給我們添加對應的Header Search Path
慨飘。
Cocoapod自動生成的目錄結構如下
所以當我們使用#import <Masonry/Masonry.h>
這種方式引用的時候,實際上我們用到的Header Search Paths
是"${PODS_ROOT}/Headers/Public"
這個路徑吞歼。同理塔猾,可以使用#import <Masonry.h>
導入,使用用到的Header Search Paths
是"${PODS_ROOT}/Headers/Public/Masonry"
路徑糯俗。
所以一般情況下老虫,我們使用Cocoapod,上述5中引用方式忽刽,除了語義導入,都可以正常使用跪帝。
Cocoapod支持非常多種設置伞剑,例如:
- 當我們
:generate_multiple_pod_projects=>true
設置市埋,開啟多project結構,此時每個Pod都是自己單獨的project抒倚,也就是說不是在同一個Pod.project
中。#import "aaa.h"
沒法通過同project索引頭文件托呕,和#import <aaa/aaa.h>
一樣项郊,可以通過Header Search Path
索引頭文件斟赚。 - 當我們使用
use_frameworks!
,此時Cocoapod不會設置Header Search Path
拗军,而是會設置Framework Search Path
食绿,此時可以使用#import <aaa/aaa.h>
正常引用。如果沒有使用多project結構器紧,那么Pod.project
目錄下的各個Pod庫铲汪,還可以使用#import "aaa.h"
互相引用,因為他們都是一個project下的狰住。但是主工程和Pod工程不是一個工程下的,所以主工程中引用Pod庫文件催植,不可以使用#import "aaa.h"
创南。同理省核,如果結合多project結構,不同Pod庫之間气忠,也不可以使用#import "aaa.h"
引用旧噪,因為此時不再在同一個project下。 - 當我們使用
use_modular_headers!
舌菜,此時Cocoapod設置Header Search Path
,此時#import <aaa/aaa.h>
和#import "aaa.h"
都可以通過Header Search Path
索引頭文件袱瓮。但是如果使用#import <aaa/aaa.h>
爱咬,會被Xcode自動替換為語義導入,即@import aaa;
燎斩。具有更優(yōu)的性能,所以推薦使用#import <aaa/aaa.h>
綜上所述栅表,當我們使用Cocoapod的時候怪瓶。
- 如果需要引用別的Pod庫中的頭文件,推薦使用
#import <aaa/aaa.h>
洗贰。 - 當Pod庫引用自己的頭文件的時候敛滋,推薦使用
#import "aaa.h"