iOS之Header Search Paths和User Header Search Paths和library searchpath、pch(prefix header)、pods文件路径

Xcode Search Paths相关配置:

参考:https://www.jianshu.com/p/9f9c1fd2e8b5html

开发的过程中,导入第三方库(framework/.a)或者下载使用别人的demo会常常会遇到一些关于库的导入的问题。而导入第三方库后,这写库的路径应该如今在导入当前项目target的Search Paths中,具体的设置路径:target -> Build Settings -> Search Paths -> Framework Search Paths 或者 Library Search Paths, 头文件在改配置中的Header Search Paths管理。c++

Framework Search Paths 管理导入的*.framework的路径
Library Search Paths 管理导入的*.a的路径
Header Search Paths 管理导入的头文件的路径xcode

Search Paths相关参数说明

  1. 导入库的时候自动生成的的路径:$(PROJECT_DIR)/XcodeForSeachPathTest/ThirdLib/zhenLib,手动拖拽的路径"$(SRCROOT)/../Frameworks/zhenFW/zhenFW.framework",很明显的区别是手动拖得有双引号,双引号的做用是若是在路径中有空格,能够识别该路径。没有双引号可是路径中有空格,咱们发现它会自动变成两个路径。缓存

  2. 路径中有空格必需要加双引号框架

  3. 多个路径能够用空格隔开,不用双引号包住函数

  4. $(SRCROOT)$(PROJECT_DIR)基本没啥区别,都是指向*.xcodeproj所在的路径post

  5. 经过../来调到上一层路径,返回上上层文件夹用../../ui

  6. $(inherited): target 的 Framework Search Paths添加$(inherited)参数会从PROJECT -> Build Settings -> Framework Search Paths里面的路径会被其继承,没有的话不会继承。因此一个项目里面有多个target,使用到了同一个库(Library或Framework)那么为了方便咱们能够在target添加继承参数,而且PROJECT统一中添加库的路径。继承的优先级:编码

    • Platform defaults
    • Project file (描述举例用这个优先级,比较经常使用)
    • xcconfig file for the Project file
    • Target
    • xcconfig file for the Target
  7. recursive:遍历该目录,non-recursive:默认路径设置;不遍历该目录。若是路径的属性为recursive,那么编译的时候在找库的路径的时候,会遍历该目录下的全部子目录的库文件。PS:在搭建项目的时候,能够建立一个专门放库文件的文件夹而且设置其属性为recursive$(PROJECT_DIR)/**至关于遍历项目文件同级下的全部路径(不推荐使用,项目大的话,影响编译的速度)。url

  8. Search Paths子选项:Header Search Paths 、User Header Search Paths的参数设置与其相同


 

 

XCode用户能够 经过Header Search Paths 来配置环境变量。但这里涉及到一个另一个参数 User Header Search Paths, 这二者到底有什么区别呢?

 

  首先明确一点,Header Search Paths 顾名思义就是用来存放 Project 中头文件的搜索根源,没有被add到项目里的头文件,能够经过配置Header Search Paths 来引入头文件,这样的好处能够不让project 包含的文件太多,便于管理。

 

     浅显一点的区别是,编码时候经过 #include 引入头文件的方式有两种 <> 和 ""。<> 是只从 Header Search Paths 中搜索, 而 "" 则能从  Header Search Paths 和  User Header Search Paths 中搜索。换言之 ,假如你把 路径加到  User Header Search Paths 中,那么 你用 #include <file.h> 的方式去引入对应的头文件,就会报错。 若是加到  Header Search Paths,  就没有问题了。

 

     具体一点的区别是,<> 是从系统目录空间 (对应 Header Search Paths)中搜索文件, "" 是从用户目录空间(对应 User Header Search Paths)中搜索文件。若是你把路径加到 User Header Search Paths 中,而 <> 没法从系统目录空间中找到新加的路径,从而报错。

 

 

 

因此在修改User Header Search Paths这个选项的时候使用

 

"$(SRCROOT)/当前工程名字/须要包含头文件所在文件夹"

 

将上面的双引号里面的字符串拷贝以后,你会发现这个$(SRCROOT)”,会自动变成当前工程因此的目录。

 

这样就能够了,发给别人,别人也不用在去修改路径了。

 

 

 

1.c/c++ 头文件引用问题

 

include <> 引用编译器的类库路径下的头文件

 

include ” 引用工程目录的相对路径的头文件

 

include 是编译指令,在编译时,编译器会将相对路径替换成绝对路径,所以,头文件绝对路径=搜索路径+相对路径。

 

Xcode Build Settings 下 Search Paths设置搜索路径

 

Header Search Paths:头文件搜索路径设置

 

$(SRCROOT)宏和$(PROJECT_DIR)宏都指xxx.xcodeproj所在的父目录

 

 

 

例如:引用工程testDemo/scr/test.h 头文件,

 

Header Search Paths中添加$(SRCROOT),引用为include scr/test.h"

 

若是在Header Search Paths中添加$(SRCROOT)/scr,那么头文件引用直接引用 include test.h”

 

 

 

1.

 

$(inherited) "$(SRCROOT) 修改.a文件的路径 --Library Search Paths

 

 $(inherited) "$(SRCROOT)/.a文件所在的文件名"

 

  //若是有多个.a文件格式就像这样

 

$(inherited) "$(SRCROOT)/xxxx" "$(SRCROOT)/xx"

 

 若是取的是相对是绝对路径那么工程移到别的地方就有可能致使运行出错。因此要改为相对路径

 

 

=========library searchpath

Project的Building Settings中得设置默认并不被Targets继承,只有当Targets的设置加入了$(inherited)时才被继承,添加目录的时候写上 “$(inherited)” 就表示从frameworks里面读取。

一种很常见的状况, 我建一个工程运行正常,可是把工程发给别人就会出现这个错误,这也是XcodeSearch Path的相对路径和绝对路径致使的。

因此在修改Library / Header Search Paths这个选项的时候使用:  "$(SRCROOT)/当前工程名字/须要包含头文件所在文件夹"

 

将上面的双引号里面的字符串拷贝以后,你会发现这个“$(SRCROOT)”,会自动变成当前工程因此的目录。这样就能够了,发给别人,别人也不用在去修改路径了。

 

 

Xcode添加静态库以及编译选项配置常见问题


一,Xcode编译出现Link错误,出现"duplicate symbols for architecture i386 clang"提示.
问题:连接时,项目有重名文件.
解决:
根据错误提示,作以下检查:
1.Taraget->Build Settings->Link Binary With Libraries检查是否有重复lib.
2.全工程搜索下重名文件,决定如何删除.

二,关于Category位于静态库时,引用该静态库的工程使用Category,出现"unrecognized selector sent to class"提示.
问题:标准UNIX静态库与Objective-C之间Linker的差别.在标准的UNIX静态库内,linker symbol是依照每个类别而产生的,但因为Category并无真正产生一个类别,因此出错.
解决:
1.在该静态库的Taraget->Build Settings->Other Linker Flags->加上 -ObjC.
2.在使用该静态库的工程Taraget->Build Settings->Other Linker Flags->加上-all_load或-force_load.

三,编译warning:ld: warning: directory not found for option '-L'.
问题:一般是Path问题.
解决:
Taraget->Build Settings->Library Search Paths 和 Framework Search Paths,删掉编译报warning的路径即OK

四,引入(带源码的)静态库所需配置.
步骤:
1.Add Files to.. 加入静态库的.xcodeproj 文件,不要勾选Copy Items.. 选项。(能够先把源代码项目先复制到使用项目文件夹下)
2.Target->Build Phases->Target Dependecies->加静态库 && Link Binary With Libraries->加静态库.
3.配置静态库头文件路径,在Taraget->Build Settings->User Header Search Paths->配上静态库的物理路径.

[错误tips: 若出现加入的.xcodeproj没法展开,则在Xcode中关闭静态库项目便可]

PS:只有.a 和 .h的静态库,则直接拖入项目便可。

五,关于重构,解决跨层调用问题,
经常使用选择:
1.传参(包括静态变量的使用)
2.传回调
3.直接移动调用的代码(若代码出如今不适合的地方,移动类/方法/etc)

之因此使用该标志,和Objective-C的一个重要特性:类别(category)有关。根据这里的解释,Unix的标准静态库实现和Objective-C的动态特性之间有一些冲突:Objective-C没有为每一个函数(或者方法)定义连接符号,它只为每一个类建立连接符号。这样当在一个静态库中使用类别来扩展已有类的时候,连接器不知道如何把类原有的方法和类别中的方法整合起来,就会致使你调用类别中的方法时,出现"selector not recognized",也就是找不到方法定义的错误。为了解决这个问题,引入了-ObjC标志,它的做用就是将静态库中全部的和对象相关的文件都加载进来。

原本这样就能够解决问题了,不过在64位的Mac系统或者iOS系统下,连接器有一个bug,会致使只包含有类别的静态库没法使用-ObjC标志来加载文件。变通方法是使用-all_load 或者-force_load标志,它们的做用都是加载静态库中全部文件,不过all_load做用于全部的库,而-force_load后面必需要指定具体的文件。

 

 

*************pch(prefix header)设置

  • 如何添加pch文件呢?
  • 向项目中添加新文件,在Other中选择PCH File:
  • 设置pch文件的路径。
    target ->Build Setting ,向搜索框输入prefix header:
  • 设置Precomplite Prefix Header 的布尔值为true,
    做用是让pch文件预编译后缓存起来,减小以后的编译时间
  • 设置Prefix Header的值为:
    $SRCROOT/(你的项目名称)/(你的pch文件名称)
    如:$(SRCROOT)/GIFMaker/GIFPrefixHeader.pch
  • 也能够直接把pch文件拖进来,可是这是绝对路径,到另一个项目回报错
  • 其中的变量SRCROOT的值为你项目所在的根目录,
    它会随着你项目的目录迁移而自动改变。

  • ok, 如今pch文件添加成功了。

***************倒入co coaPods后的文件路径问题---CocoaPods导入第三方库,提示找不到头文件的解决方法

经过cocoaPods倒入框架后;找到TARGETS -> Build Settings -> SearchPaths -> User Header Search Paths  在后面的空白处双击;在Header search path中新增一个值”$(PODS_ROOT)”,而且选择”recursive”,这样Xcode就会在项目目录中递归搜索文件且会自动找到Pods文件,头文件自动补齐功能立刻就好使了.

 

***************项目里有该文件,可是仍是显示找不到。或者是cocopods打开的项目。

缘由:.h文件路径找不到。具体找不到的缘由有不少种。

可能pods 的头文件找不到

#import "Reachability.h"找不到

首先找到下面配置文件:

Reachability-Private.xcconfig

 查看里面内容:

#include "Reachability.xcconfig"

GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1

HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/Reachability" "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/MKNetworkKit" "${PODS_ROOT}/Headers/Public/MKNetworkKit/Categories" "${PODS_ROOT}/Headers/Public/Reachability"

OTHER_LDFLAGS = ${REACHABILITY_OTHER_LDFLAGS}

PODS_ROOT = ${SRCROOT}

SKIP_INSTALL = YES

上面标红的地址,去文件夹看看相应路径是否存在该文件,常常是在别的文件夹下面。