Files
knowledge-kit/Chapter1 - iOS/1.51.md
2020-02-25 17:46:51 +08:00

8.1 KiB
Raw History

Pod

1. 组件的地址

我们在做组件化的时候经常将一些业务模块封装打包,做成 pod 管理的形式,然后当在开发的时候需要修改一些模块化的代码。

当维护好组件的时候我们可能在一个新的工程设置好 podfile 引入组件,但是有可能需要继续修改组件的源代码,代码需要可编辑。所以我们可能需要将 Podfile 中的 pod 源修改为本地。 然后安装 pod install 后就可以看到在项目文件里面有可编辑的组件代码

pod 'GoodsCategoryModule', :path => '../GoodsCategoryModule'
#pod 'GoodsCategoryModule',:git => 'git@gitlab.xxx.com:forntend_ios/GoodsCategoryModule.git',:branch => 'release/Appstore'

注意点:

  1. 我们本地的组件源代码需要和 pod 文件中的代码工程文件名称一致
  2. 注释掉远端仓库的地址 path 后面是相对路径

2. 组件库使用 pch 头文件

///一个区分开发和线上环境的Log。NSLog的本质是调用对象方法的 description 方法所以线上代码使用NSLog会造成性能和安全问题
#ifdef DEBUG
    #define SafeLog(...) NSLog(__VA_ARGS__)
#else
    #define SafeLog(...)
#endif

所以我们需要对各个组件库里面的 NSLog 进行改造,变成 SafeLog。没做特殊处理,当你在 pod 库的 pch 文件写好代码,发现主工程执行 pod install 之后,看到之前写的 SafeLog 代码不见了。所以我们需要指定 pch 文件。 操作:

  • 新建 PrefixHeader.h 头文件
  • 在当前 pod 库的 ***.podspec 文件中写如下代码
  s.prefix_header_contents = '#import "PrefixHeader.h"'

说明:该代码的作用相当于将 PrefixHeader.h 文件写入到当前 pod 库 XQTriggerKit-prefix.pch 文件的最后一行。相当于

#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif

#import "PrefixHeader.h"

缺点:项目存在多个 pod 组件库。主工程修改 pch 还好,但是每个 pod 库都去新建 PrefixHeader.h 文件和 podspec 文件添加一行代码。工作量非常大。

改进方案:对 NSLog 进行 Hook。

步骤:

  • 引入 fishhook 库
  • 新建 SafeLog.h 和 SafeLog.m 文件
  • 在 SafeLog.m 文件的 load 方法中对 NSLog 进行 hook判断是 Debug 环境就打印。代码如下
#import "SafeLog.h"
#import "fishhook.h"

// orig_NSLog是原有方法被替换后 把原来的实现方法放到另一个地址中
// new_NSLog就是替换后的方法了
static void (*orig_NSLog)(NSString *format, ...);

@implementation SafeLog

void(new_NSLog)(NSString *format, ...)
{
    va_list args;
    if (format) {
        va_start(args, format);
        NSString *message = [[NSString alloc] initWithFormat:format arguments:args];
        #ifdef DEBUG
            orig_NSLog(@"%@", message);
        #endif
        va_end(args);
    }
}

+ (void)load
{
    rebind_symbols((struct rebinding[1]){ {"NSLog", new_NSLog, (void *)&orig_NSLog} }, 1);
}

@end

3. CocoPods 指定版本号带 ~> 与不带的区别

  • 带 ~> 是指库版本号的一个范围。大于等于指定的版本号,小于高一位的版本号
  • 不带 ~> 是指固定的版本号
pod 'aaa', '~> 0.1.2'  // 大于等于 0.1.2 且小于 0.2
pod 'bbb', '1.1' 版本号指定为 1.1

4. 查看当前 Pod 库被何处引用

出于某种原因经常会需要查看当前 Pod 库被何处引用了你需要修改组件库A然后A修改完之后可能需要在依赖组件库A的地方去修改版本号。这时候就需要查询了例子可能不优雅但是确实有需要查询引用的情况有轮子

  • 先下载所需要的库
gem install reversepoddependency
  • 利用脚本在我们的组件库 repo 中去查询
specbackwarddependency /Users/liubinpeng/.cocoapods/repos/51xianqu-xq_specs(本地CocoPod repo地址) xq_baaidumapkit(组件库名称)

鉴于这个命令比较长,且本人使用的是 iTerm2+Zsh所以将命令写入到 .zshrc 文件中, source 编译链接过可以快速使用。例如 repoanalysis xq_baaidumapkit

alias repoanalysis='specbackwarddependency /Users/liubinpeng/.cocoapods/repos/51xianqu-xq_specs' 

Pod组件库依赖分析

具体的操作步骤可以参考我的这个文章

5. lint 的时候安装一些神奇的依赖

在对 App 做应用包瘦身的时候发现了一些问题。某个组件库 lint 的时候通过终端的信息,发现安装了一些不是 podspec 里面指定的依赖仓库。百思不得其解,同事说可能是之前的某个版本依赖了这些项目。有了这个思路就好办事了。

遇到问题

  • 打开本地的 /Users/liubinpeng/.cocoapods/repos 文件夹。查看本地的私有 repo 的管理的所有的项目,找到出问题的 repo进去删掉有问题的 tag。
  • 出问题的 repo 将远端的有问题的 tag 也删掉
  • 删除远端的 repo 仓库的有问题的 tag。

6. lint 失败 - 报错为 error: invalid task ('StripNIB...

Build system information
    error: invalid task ('StripNIB /Users/liubinpeng/Library/Developer/Xcode/DerivedData/App-fgbnpsgtrtstroctiqnanvyrfwyr/Build/Products/Release-iphonesimulator/XQLoginModule/SDGMemberCardBindViewController.nib') with mutable output but no other virtual output node (in target 'XQLoginModule')

原因为 xib 和图片资源都属于资源文件不可以放在源文件Classes需要放在 Assets 中。如果放到 Classes 文件夹中 lint 会报错。

7. 一台电脑安装了最新版本的,出问题删除最新版 Xcode下载旧版本 Xcodepod install 失败

You need at least git version 1.8.5 to use CocoaPods
  • 可能是cocoapods安装成功了但是链接Xcode的版本过低所以需要更新Xcode
  • 电脑安装了多个版本的Xcode就需要修改链接Xcode路径改成链接电脑比较高版本的Xcode。
    sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
    

8. 一台电脑安装了最新版本的,出问题删除最新版 Xcode下载旧版本 Xcode打开工程 Xib 报错

  • sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService
  • xcrun simctl erase all

9. 开发电脑上安装了旧版本 Cocopods,Mac 系统升级后, pod lint 失败

解决方案: 将 fourflusher 仓库中上的 find.rb 文件中的 ruby 脚本复制到本地的 fourflusher 下.

查找本地 fourflusher 文件夹所在位置.

gem which fourflusher

我的电脑 find.rb 文件所在位置. /Library/Ruby/Gems/2.6.0/gems/fourflusher-2.3.1/lib/fourflusher/find.rb

注意: 文件保存需要权限,所以加 sudo

10. pod lint 产生的信息太多,一屏显示不全,但是出错之后我们可能需要去查看 error 信息,上下翻页不方便

解决方案: 利用脚本 >1.log 2>&1 将当前的 pod lint 产生的信息写入文件.

完整代码

 pod lib lint --sources=****,**** --allow-warnings --verbose --use-libraries >1.log 2>&1

11. pod 库每次修改代码,主工程必须 clean 再安装才可以看到新改动的代码

解决方案:

install! 'cocoapods', :disable_input_output_paths => true

12. pod 库太多,每次构建编译都很耗费时间

install! 'cocoapods', generate_multiple_pod_projects: true

13. 卸载旧版本 cocoapods 安装新的

 sudo gem uninstall cocoapods-core cocoapods cocoapods-deintegrate cocoapods-downloader cocoapods-plugins cocoapods-search cocoapods-stats cocoapods-trunk cocoapods-try coderay colored2 concurrent-ruby cocoapods-clean
sudo gem install cocoapods