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


    Xcode Search Paths相关配置:

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

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

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

    Search Paths相关参数说明

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

    路径中有空格必须要加双引号

    多个路径可以用空格隔开,不用双引号包住

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

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

    $(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
    recursive:遍历该目录,non-recursive:默认路径设置;不遍历该目录。如果路径的属性为recursive,那么编译的时候在找库的路径的时候,会遍历该目录下的所有子目录的库文件。PS:在搭建项目的时候,可以创建一个专门放库文件的文件夹并且设置其属性为recursive。$(PROJECT_DIR)/**相当于遍历项目文件同级下的所有路径(不推荐使用,项目大的话,影响编译的速度)。

    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

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

    签 名:被别人嫉妒,说明你卓越;你嫉妒别人,说明你无能。 座右铭:抓紧一切时间睡觉。
  • 相关阅读:
    ssh 私匙登录, 文件rswrst权限
    从内存使用的角度来理解.Net底层架构
    (转)C#为什么要使用Invoke,它和BeginInvoke有什么区别
    如何通过微信自定义菜单跳转到自己的网站
    (转)HubbleDotNet+Mongodb 构建高性能搜索引擎--概述
    (转)HubbleDotNet 和 Lucene.net 性能对比测试
    C#异步提示和技巧
    关于System.Windows.Forms.DateTimePicker的一个Bug
    关于frameset中指定区域回退的实现
    java.lang.NoClassDefFoundError Adding a jar to an RCP application
  • 原文地址:https://www.cnblogs.com/baitongtong/p/14944206.html
Copyright © 2020-2023  润新知