IOS基础流程:Git与CocoaPods

原创:知识点总结性文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
温馨提示:由于简书不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容

目录

  • 一、Git
    • 1、简介
    • 2、安装和使用
    • 3、常用命令
  • 二、使用 CocoaPods 工具管理依赖库
    • 1、安装 cocopods
    • 2、安装框架
    • 3、cocoapods常见问题和解决办法
  • 三、制作cocoapod库
    • 1、iOS 组件化/模块化的需求
    • 2、cocoapod 的原理
    • 3、创建框架工程
    • 4、配置 .podspec 文件
    • 5、更新 GitHub 里面的库
    • 6、提交 .podspec 文件到 CocoaPods
    • 7、使用创建的库
    • 8、创建过程遇到的问题
  • 四、python3.7
    • 1、安装 python3.7
    • 2、使用 python3.7
    • 3、Mac上Python安装request库老是失败的问题
  • 参考文献

一、Git

1、简介

a、管理模式
  • 集中管理模式:SVN
  • 分布式管理模式:有一个中心代码库,每位团队人员本地也都有代码库
  • 代码库 (repository): 存放项目代码以及历史备份的地方
  • 分支 (branch):用于验证和实验一些想法、版本发布、缺陷修改
  • 合并分支 (merging branch)
  • 签出 (checkout):从代码库获得文件或目录,将其作为副本保存在目录下
  • 提交 (commit):修改的文件或目录作为新版本复制回代码库
  • 冲突 (conflict)
  • 解决 (resolution):需要人为干预解决,以接受一组更改并删除另一组更改
  • 索引 (index):快照

b、Git 还有成熟的代码托管服务 GitHub 网站
  • 如果项目不需要与其他开发人员协同开发,我们就不需要Git服务器。
  • 任何能够提供通信协议和安全认证的代码库, 都可以认为是服务器。
  • HTTP(S)协议和 SSH协议都可以支持远程库读写 、身份认证等操作。
  • Git常用的协议是SSH协议,我们需要在本机上生成公钥后,将公钥提供给GitHub网站
  • 只有付费账户才可以创建私有库
  • 选中Initialize this repository with a README 复选框创建一个README文件,用来说明这个代码库的用途
  • 但此时代码库中还是空的,我们需要在本地电脑中推送一个 Xcode项目到GitHub代码库
  • 通过 SourceControl- Push菜单项推送到GitHub服务器 ,其中选择 Remoteorigin/master
  • 派生与Git中的分支很像,可以把它理解为代码库级别的分支,把Fork代码库派生到当前账户下面了
  • 点击Transfer按钮,输入要转移的代码库和新的拥有者
  • 组织中会有管理员,他可以管理代码库,对代码库重新命名 、 删除和转移
  • 普通成员对代码库可以接受推送请求、合并推送

c、注意点
  • 每天修改量在10M以内,尽量每天提交修改,防止一次性提交造成大量代码冲突问题
  • 每次push之前一定需要先进行pull操作,先将本地更新再提交自己的修改
  • 遇到冲突,可以使用如 $ open ucareshop/AppDelegate.m 打开文件的冲突部分将其删除
  • 切换到分支再git push,之后等代码审核通过了再更新到master

2、安装和使用

a、安装镜像

使用以下命令添加 TUNA 源并移除 gems 默认源。

gem sources --add https://mirrors.tuna.tsinghua.edu.cn/rubygems/ --remove https://rubygems.org/
❷ 列出已有源,应该只有 TUNA 一个
xiejiapei@MacBook-Pro ~ % gem sources -l
*** CURRENT SOURCES ***

https://mirrors.tuna.tsinghua.edu.cn/rubygems/

b、配置 Git 的用户信息

当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址

git config --global user.name "Xie Jiapei"
git config --global user.email jiapei@ucarinc.com

c、Git 通常使用流程
// 切换到本地想安装的目录
$ cd Desktop/

// 安装Github上的项目
git clone http://gitlab.10101111.com:8888/jiapei.xie/gitlearn.git

// 切换进该项目目录
$ cd gitlearn/

将本地想要添加的文件拖进到下载下来的项目中

// 切换到分支,不影响 mainTree
$ git checkout develop

// 将拖进来的文件添加到项目中
git add .

// 本地提交,写好提交原因
git commit -m "init"

// 先拉下来远程Github上的最新内容
// git pull命令是git fetch和git merge命令的一个组合
git pull

// 再将自己修改后的内容提交到远端
git push

// early EOF 倘若文件太大则需要配置提交的缓存大小
git config --global http.postBuffer 15728640 

d、完成 Xcode 中GitHub帐号的设置

点击「+」按钮添加帐号并选择 GitHub 之后,你会发现此处需要填写 AccountToken。其中 AccountGitHub 用户名,Token 则是一个特殊的许可,它允许 Xcode 使用你的 GitHub 帐号管理你的 Remote Repository 远程仓库。

进入 GitHub 设置页面,点击右上角的「Generate new token」即可生成一串许可数字,将这串数字复制回到 Xcode 登录界面的 Token 文本框中,并点击「Sign In」登录即可完成 GitHub 帐号的设置。


3、常用命令

查找命令的帮助信息
% git help
目录和文件
// 新建目录
% mkdir learngit  

// 用于显示当前目录路径
% pwd 

// 回到上一级 
% cd ..  

// 新建文件
% touch readme.txt

// 查看文件内容
% cat Podfile

// 查看文件状态,用于解决冲突
% git status

// 查看所有文件 
% ls -al 
分支
// 创建仓库
% git init 这个目录默认是隐藏的

// 创建并切换到分支
% git checkout -b develop

// 切换到master
% git checkout master

// 删除分支
% git branch -d develop
vim 文本编辑器
// 进入vim文本编辑器
% vim readme.txt 

// 保存修改并退出
wq (或者shift zz)

// 忽略文件
% vim .gitignore  
log 日志
// 历史记录
% git log

// 如果嫌输出信息太多看得眼花缭乱,可以使用以下语法
% git log --pretty=oneline

// 如果只想看最近几条的数据
% git log -n 1

// 例如
1 file changed:1个文件被改动(我们新添加的readme.txt文件)
2 insertions:插入了两行内容(readme.txt有两行内容)
reset 回退
// 寻找版本号
% git reflog

// 文件的索引:文件内容的哈希值
5e9ae2dd

// 回退机制,上上一个版本就是HEAD^^,上100个版本写成HEAD~100,版本号没必要写全,前几位就可以了
% git reset --hard HEAD^(版本号)
% git reset HEAD  readme.txt

// 回滚版本
% git revert 

// 删除文件
% rm test.txt

二、使用 CocoaPods 工具管理依赖库

1、M1 MacBook安装cocoapods

CocoaPods搭建了一个中心库, 第三方库被收录到该中心库中,没有收录的第三方库是不能使用CocoaPods管理的,这就是所谓的"中心化“思想。

CocoaPods在下载第三方库后,会将其编译成静态链接库或动态框架文件,然后会修改Xcode项目属性,配置依赖关系,这就是"侵入性"。

mac m1笔记本都会自带可用的ruby版本,也就是不需要你去升级ruby,因为升级它还要装homebrew,你装这个又会遇到一些坑,所以能用系统自带的就用它。你可以用如下命令查看系统的ruby版本:

ruby -v
ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin22]

查看ruby镜像源sources的命令:

gem source -l
*** CURRENT SOURCES ***

https://rubygems.org/

https://rubygems.org/ 这个源在国内是访问不到的,所以你需要先移除这个镜像,然后添加国内可访问的镜像 https://gems.ruby-china.com/(只保留这一个镜像),使用如下命令:

gem sources --remove https://rubygems.org/
gem sources --add https://gems.ruby-china.com/
https://rubygems.org/ removed from sources
https://gems.ruby-china.com/ added to sources

再验证下就会发现变成了https://gems.ruby-china.com/

*** CURRENT SOURCES ***

https://gems.ruby-china.com/

你需要更新最新的xcode命令工具,用下面命令,如果已经更新了他会提示已经是最新的,没有的话会提示你是否安装,你只要确认安装就行:

xcode-select --install
xcode-select: error: command line tools are already installed, use "Software Update" in System Settings to install updates

然后安装最新的cocoapods,使用如下命令:

sudo gem install cocoapods -n /usr/local/bin
......
34 gems installed

出现错误:

ERROR:  While executing gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/gems/2.6.0 directory.

安装 Homebrew 和命令行工具:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Homebrew 可能会要求您在安装后运行一些命令:

echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> /Users/xiejiapei/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)" 

检查到目前为止一切是否正常:

brew doctor

使用 ruby-install 安装 chruby 和最新的 Ruby:

brew install chruby ruby-install
ruby-install ruby

配置 shell 文件:

echo "source $(brew --prefix)/opt/chruby/share/chruby/chruby.sh" >> ~/.zshrc
echo "source $(brew --prefix)/opt/chruby/share/chruby/auto.sh" >> ~/.zshrc
echo "chruby ruby" >> ~/.zshrc

查看当前 ruby 版本:

ruby -v

重新安装:

gem install cocoapods

查看当前 pods 版本:

pod --version
1.11.3

查看pods源:

pod repo list
0 repos

但是你使用pod search AFN时你就发现它报错了,其实它是m1芯片与ruby不兼容问题,错误如下(或者其他错误信息都可以使用这种方法试试):

LoadError - dlopen(/Library/Ruby/Gems/2.6.0/gems/ffi-1.13.1/lib/ffi_c.bundle, 0x0009): missing compatible arch in /Library/Ruby/Gems/2.6.0/gems/ffi-1.13.1/lib/ffi_c.bundle - /Library/Ruby/Gems/2.6.0/gems/ffi-1.13.1/lib/ffi_c.bundle

解决它首先找到finder(访达),然后找到应用程序选项,在找到实用工具文件,点击进去找到终端,然后右键点击它,选中"显示简介",你会发现一个选项使用Rosetta打开,对,问题的关键就是这个选项,要勾选它,关闭后重启终端后你还要输入命令让它生效,命令如下:

sudo gem install ffi

然后你再去执行pod命令pod search AFN就成功了。


2、安装框架

❶ 在项目根目录下建立 Podfile 文件,然后修改其中的内容
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'UseUIControlFramework' do
 
pod 'DZNEmptyDataSet'
pod 'MGSwipeTableCell'
pod 'FSCalendar'
pod 'Toast'
pod 'MBProgressHUD'
pod 'zhPopupController'
pod 'Masonry'

end
❷ 明确第三方版本号

指定依赖库名一般是指 GitHub上库的项目名,这个名字如果不能确定, 需要到 GitHub上查询确定。

pod 'AFNetworking'// 不显式指定依赖库版本,表示每次都获取最新版本
pod 'AFNetworking', '5.0'// 只使用5.0版本    
pod 'AFNetworking', '> 5.0'// 使用高于5.0的版本    
pod 'AFNetworking', '>= 5.0'// 使用大于或等于5.0的版本    
pod 'AFNetworking', '< 5.0'// 使用小于5.0的版本    
pod 'AFNetworking', '<= 5.0'// 使用小于或等于5.0的版本    
pod 'AFNetworking', '~> 4.5'//使用大于等于4.5但小于5.0的版本     
❷ 打开终端安装框架
xiejiapei@xiejiapeis-iMac Example % pod install

Analyzing dependencies
Downloading dependencies
Installing XJPCategoryKit 0.1.0
Generating Pods project
Integrating client project
Pod installation complete! There are 3 dependencies from the Podfile and 3 total pods installed.

3、cocoapods常见问题和解决办法

iOS工程在组件化的过程中难免会碰到cocoapods的一些疑难问题,而网上的资料鱼龙混杂,严重阻碍开发进程。

问题1:podspec文件lint不通过或者无法push

加了—verbose可以看到Error提示:

Xcodebuild error: Unable to find a destination matching the provided destination specifier:

{ id:DB7BC0D9-CA24-4CA5-8FE9-AE322FD7B059}

解决办法:在xcode的simulators中找到这个id的模拟器,删除,重试命令。如果仍然出现该提示,再删再试,直到所有把出错的模拟器都删了就好了。怀疑新版的cocoapods(1.10.1)查找不到Xcode后安装添加的模拟器。

问题2:pod库加了新文件,删了原标签(0.1.1),在新的commit上重新打这个标签(还是0.1.1),主工程pod install/update,都无法download到新文件

原因:本地有缓存
解决办法:

cd ~/Library/Caches/CocoaPods/Pods/Release   // pod库缓存的文件
rm -r 删除这个库

重新pod install即可。

问题3:pod库里的swift代码,依赖OC的库(比如叫NEToolKit),编译不过

解决办法:在swift文件开头添加一行代码:

import NEToolKit
问题4:pod install 提示文件重复

主工程Podfile同时引入A、B两个pod,A依赖B,但是这两个B的版本不同,需要在A的pod工程下执行pod update,将A使用的B的版本更新到最新,然后主工程再pod install,这样就不会发生引入了两个版本的B导致的文件重复了。

问题5:pod repo push时提示Found multiple specifications for ''*

原因:pod repo list发现同时存在cocoapods和trunk,导致specifications重复。但是pod repo remove trunk后再pod repo pushtrunk会被自动创建,仍然会出现该错误提示

解决办法:pod repo push时加上-sources='https://github.com/CocoaPods/Specs.git',指定specifications的来源。

问题6:pod repo push时提示错误podspec specification does not validate

原因:低级错误,podspec指定的version没打tag

问题7:swift的pod(比如叫LFTWidget)使用了oc的pod(比如叫NEToolKit),pod install失败,提示如下错误信息:
[!] The following Swift pods cannot yet be integrated as static libraries

The Swift pod `LFTWidget` depends upon `NEToolKit`, which does not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set `use_modular_headers!` globally in your Podfile, or specify `:modular_headers => true` for particular dependencies.

原因:在私有库中不能使用bridging-header.h桥接文件,swift只能通过swift module机制来引用其他oc模块。

解决办法:podfile里将依赖的OC库挨个加上:modular_headers => true

问题8:提示libyary找不到

原因:一般libyary找不到,都是searchPath的问题。在project里,TestRelease的配置是一样的;而在Pod里,hook的时候会更改配置,将Release也配置成和Test一样,就好了。一般poddependency的时候引用是没有问题的,但如果pod里面的层级比较多,在hook的时候就要加inhertied

解决办法:podfile文件里添加如下代码(供参考):

post_install do |installer|

  installer.pods_project.targets.each do |target|

    target.build_configurations.each do |configuration|

      if configuration.name == 'Debug'

        configuration.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)','DEBUG=1']

      elsif configuration.name == 'Test'

        configuration.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)','TEST=1']

      elsif configuration.name == 'Release'

        configuration.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']

      end

    end

  end

end

三、制作 cocoapod 库

1、iOS 组件化/模块化的需求

当 App 的功能逐渐庞大,开发人员越来越多的时候,就会出现各种各样的问题。这时合理的组织架构就变得尤为重要,通常的做法就是将 App 内的功能进行模块化。只有项目到达一定规模后,开始出现相对独立的业务,团队人员开始增加,单一项目的开发模式成为了开发效率的掣肘,这个时候才是应该开始做组件化的时候。

问题
  • 代码量庞大,相同功能代码可能反复被实现,导致编译速度变慢
  • 功能交织,难以抽离,导致问题排查难度加大,提交时容易出现冲突
  • 只要一处出现错误就会导致整个项目难以运行
模块化
  • 按照功能将项目分成不同的模块,不同的人员维护不同的模块,这样可以使责任清晰
  • 不经常改动的代码做成模块之后就不需要再编译整个项目,这样可以增加编译速度
  • 模块之间相互独立,减少依赖,不容易出现代码提交冲突
盲目组件化导致开发效率变低
  • 两三个人开发的简单项目,组件化的解耦反而可能会导致代码逻辑变复杂
  • 组件化粒度过细也会导致一个业务需求需要修改多个组件,容易让代码追踪变得困难
  • 与对应组件负责人的沟通会拖慢开发的进度

2、cocoapod 的原理

点开Specs后,在This repository里输入AFNetworking进行搜索。

CocoaPods帮我们管理第三方和自己的库,它本身也是一个.xcodeproject工程,只不过它是专门管理第三方和自己的库的工程。它的工作原理就是:你把.podspec文件制作好,然后trunk push 给它,它再把.podspec文件保存为.podspec.json文件放到GitHub,你需要的话,它通过这个.podspec.json文件把GitHub上对应的开源库的文件下载下来,放到你的工程里。


3、创建框架工程

a、在 GitHub 上新建一个仓库

b、区分私人框架和公共pods库不同的创建方式

很多教大家制作pods的教程令人感到可笑又可恨,他们连最基本的如何创建框架工程都没告诉大家,导致很多小白忙活了半天还是在做APP而不是在做框架,还由于造成了一堆意外错误而浪费了大量时间。

创建框架工程

不要用上面👆这个来创建工程。作为小白的我最初就是由于分不清私人框架和公共pods库不同的创建方式,使用了上面的方式创建了私有框架来进行下面的流程导致了一大堆莫名其妙的诡异错误,浪费了很多时间。


c、创建相应的模板工程

正确的步骤是使用下面的方式来创建公共的pods库。

xiejiapei@xiejiapeis-iMac Desktop % pod lib create XJPCategoryKit

在终端运行以上命令后会进入后续的选择流程,cocopods通过这些选择会为你创建相应的模板工程,包括框架、使用的示例和测试。

Cloning `https://github.com/CocoaPods/pod-template.git` into `XJPCategoryKit`.
Configuring XJPCategoryKit template.

What platform do you want to use?? [ iOS / macOS ]
 > iOS

What language do you want to use?? [ Swift / ObjC ]
 > ObjC

Would you like to include a demo application with your library? [ Yes / No ]
 > Yes

// 你应该测试你的库,测试可确保使用您库的人员的稳定性,建议使用测试框架,而不是依赖Apple的XCTest
Which testing frameworks will you use? [ Specta / Kiwi / None ]
 > Specta

// 根据您所构建的内容库,你可能会发现快照基于测试是验证结果的聪明的方式
Would you like to do view based testing? [ Yes / No ]
 > Yes

// 使CocoaPods生成的所有类都适合您的样式,所有从Xcode内部生成的类都将以您的前缀开头
What is your class prefix?
 > XJP

Downloading dependencies
Installing Expecta (1.0.6)
Installing Specta (1.0.7)
Installing XJPCategoryKit (0.1.0)
Generating Pods project
Integrating client project

[!] Please close any current Xcode sessions and use `XJPCategoryKit.xcworkspace` for this project from now on.
Pod installation complete! There are 3 dependencies from the Podfile and 3 total pods installed.

 Ace! you're ready to go!
 We will start you off by opening your project in Xcode
  open 'XJPCategoryKit/Example/XJPCategoryKit.xcworkspace'

创建完成后自动打开的pod库工程目录如下。


d、拖入项目文件

将自己的工程文件拖入到项目中,需要分成两个部分,一个部分放资源文件,另外一个部分放自己的工程文件,这个架构很重要!!!

分类框架
录音框架

再将这些文件导入到工程中。你可能会好奇为什么在Classes目录下的文件在工程目录中跑到了XJPCategoryKit文件下,这个无需担心,系统会根据XJPCategoryKit.podspec文件自动进行关联,不信你在Classes目录下删除个文件试试,工程目录中XJPCategoryKit文件下的该文件马上会爆红表示不存在该文件了。

XJPCategoryKit的工程目录

提示下,这里有个小技巧,将项目文件拖入到文件夹后无需再回到工程中重复导入,而是可以直接在终端执行pod install就可以更新工程目录了。

DriverRecordSoundKit的工程目录

e、解决被墙屏蔽导致的超时问题

运行pod install后可能会遇到被墙屏蔽导致的超时问题。

[!] CDN: trunk Repo update failed - 22 error(s):
CDN: trunk URL couldn't be downloaded: https://cdn.jsdelivr.net/cocoa/Specs/5/0/9/FBSnapshotTestCase/1.1/FBSnapshotTestCase.podspec.json Response: Timeout was reached

解决方案是进入到Podfile文件中,添加清华大学开源软件镜像站。

source 'https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git'

再执行如下命令清除当前的 trunk

pod repo remove trunk

再次尝试 pod install就可以了。

xiejiapei@xiejiapeis-iMac repos % pod repo remove trunk
Ignoring ffi-1.12.2 because its extensions are not built. Try: gem pristine ffi --version 1.12.2
Removing spec repo `trunk`
xiejiapei@xiejiapeis-iMac repos % cd /Users/xiejiapei/Desktop/XJPCategoryKit/Example

xiejiapei@xiejiapeis-iMac Example % pod install
Ignoring ffi-1.12.2 because its extensions are not built. Try: gem pristine ffi --version 1.12.2
Analyzing dependencies
Downloading dependencies
Installing Expecta (1.0.6)
Installing Expecta+Snapshots (3.1.1)
Installing FBSnapshotTestCase (2.1.4)
Installing Specta (1.0.7)
Installing XJPCategoryKit (0.1.0)
Generating Pods project
Integrating client project

[!] Please close any current Xcode sessions and use `XJPCategoryKit.xcworkspace` for this project from now on.
Pod installation complete! There are 5 dependencies from the Podfile and 5 total pods installed.

更新工程目录后如下。

库工程目录

4、配置 .podspec 文件

podfile文件想必大家都应该很熟悉才是,它可以方便管理第三方库的使用。podspec文件其实就是一个pod的配置文件,里面记录这个pod的配置信息、编译依赖、仓库地址以及版本信息等等,本地的.cocoapod文件夹其实就是存储了每个podpodspec文件(不过是JSON格式)。每个pod install就是去通过找podspec的仓库地址,再去下载相应的源码。

a、创建 .podspec 文件,create 后面必须是开源库名

podspec文件会自动生成,假如不小心删除掉了,则可以通过以下的方式进行创建。

xiejiapei@xiejiapeis-iMac desktop % cd /Users/xiejiapei/Desktop/DriverRecordSoundKit
xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % pod spec create DriverRecordSoundKit

Specification created at DriverRecordSoundKit.podspec

使用Sublime Text打开podspec文件后阅读注释

Be sure to run `pod spec lint RecordSoundKit.podspec' to ensure this is a valid spec and to remove all comments including this before submitting the spec.

在你提交.podspec文件到CocoaPods前,务必要在命令行运行 pod spec lint RecordSoundKit.podspec 来确保.podspec有效,并且删除所有的注释,包括这句(Be sure ... submitting the spec.)

b、podspec 文件的语法说明
Pod::Spec.new do |spec| #表示用spec作为代称
    ...
end
开源库描述信息
#开源库的名字
spec.name         = "DriverRecordSoundKit"

#开源库当前版本
spec.version      = "1.0.0"

#开源库概述(打开GitHub能看到的描述)
spec.summary      = "使用场景包括:司机行驶过程、会议、课程等的全程录音"
#开源库描述 (这个描述会被用来生成开源库的标签,必需写在中间一行)
spec.description  = <<-DESC
1. 部分城市运管部门要求网约车需提供服务过程中录音功能
2. 与高德等聚合平台对账时,对于部分争议作弊订单,需要行程中录音证据
3. 司乘发生纠纷时,有行程中录音可方便责任判定,并且行程中录音功能的存在,可在一定程度上避免一些恶意投诉或司机不规范服务
4. 便于业务部门抽查司机服务规范情况,例如人工抽查或语音质检
5. 本录音工具类也可用于会议或者上课等场景进行全程录制
                 DESC
#可以是开源库的GitHub地址
spec.homepage     = "https://github.com/xiejiapei-creator/DriverRecordSoundKit"

#协议
spec.license      = "MIT"

#开源库作者
spec.author             = { "jiapei.xie" => "2170928274@qq.com" }

#开源库作者的社交链接(此处我放的是简书)
spec.social_media_url   = "https://www.jianshu.com/u/1ceb4a330607"

#开源库支持的平台(暂时没考虑tvOS、OSX等)
spec.platform     = :iOS

#开源库最低支持
spec.ios.deployment_target = "10.0"

#支持的swift版本
spec.swift_version = "4.0"
使用到的依赖库
#是否使用静态库。如果podfile指明了use_frameworks!命令,但是pod仓库需要使用静态库则需要设置
spec.static_framework = true

#开源库GitHub的路径与tag值,GitHub路径后必须有.git,tag实际就是上面的版本
spec.source       = { :git => "https://github.com/xiejiapei-creator/DriverRecordSoundKit.git", :tag => "#{spec.version}" }

#开源库头文件
spec.public_header_files = 'DriverRecordSoundKit/DriverRecordSoundKit.h'
#私有库依赖的三方库
spec.dependency 'AFNetworking', '~> 1.0'

#指定私有库文件是否是ARC,默认是true,表示所有的 source_files是arc文件
spec.requires_arc = true

#pod库使用的系统库
spec.ios.framework = 'CFNetwork'
spec.frameworks = 'QuartzCore', 'CoreData'

#libraries使用的静态库 比如libz、sqlite3.0等,如果有多个则用逗号分开
spec.ios.library = "xml2"
spec.libraries = 'xml2', 'z'
项目资源与文件路径
#自定义前缀文件,默认是true cocoapos会生成默认前缀.pch文件
spec.prefix_header_file = false
spec.prefix_header_file = 'iphone/include/prefix.pch'

#pod文件路径
#一个宗旨:库里面每个文件、资源都要有路径指向它
spec.source_files = "Classes/*.{h,m}" #表示匹配所有Classes目录下文件,不包含子目录的
spec.source_files = "Classes/**/*.{h,m}" #表示匹配所有.h、.m结尾的文件(主目录和子目录,其中**相当于省略中间层级)
spec.source_files = 'Classes/**/*.{h,m}', 'More_Classes/**/*.{h,m}'
s.source_files = "UnionPay/**/*.{h, mm}"

#公共头文件,这些头文件将暴露给用户的项目。如果不设置,所有source_files的头文件都将被暴露
#private_header_files.和public_header_files相反,指定不暴露的头文件
spec.public_header_files  =  'Headers/Public/*.h'
#依赖的框架
s.dependency 'UCARLogger'

#指定三方库的路径
spec.ios.vendored_frameworks = "MyPod/Frameworks/MyFramework.framework"
spec.vendored_frameworks = 'MyFramework.framework', "TheirFramework.framework"

#三方静态库,指明具体路径
spec.ios.vendored_library = "Libraries/libProj4.a"
spec.vendored_libraries = 'libProj4.a', 'libJavaScriptCore.a'
s.ios.vendored_libraries = "UnionPay/**/*.a"
s.vendored_libraries = 'UCARFaceID/UCarLive/MGBaseKit/libMobileSDKAuth.a', 'UCARFaceID/UCarLive/FacePlusPlus/libliveness.a'
#系统的框架
s.frameworks = "CFNetwork", "SystemConfiguration"
s.framework = 'CoreMotion', 'CoreMedia', 'AVFoundation'
s.frameworks = "Foundation"

#系统的静态库,需要去掉lib前缀
s.library = 'c++', 'z'

#资源文件
s.ios.resource_bundle = { 'MapBox' => 'MapView/Map/Resources/*.png' }
s.resource_bundles = {   'XBPodSDK' => ['XBPodSDK/Assets/**']}
s.resource = "FaceID/MGLiveResource.bundle"
s.resource_bundles = { 'PushEngine' => ['PushEngine/Assets/*.plist'] }

#被排除的文件
spec.ios.exclude_files = "Classes/osx"
spec.exclude_files = 'Classes/**/unused.{h,m}'
私有库模块
#Subspecs 私有库模块
spec.subspec 'ConvertMP3' do |ss| #简单
  ss.source_files = 'DriverRecordSoundKit/ConvertMP3.h' #指定子模块路径
end

#Subspecs 私有库模块
spec.subspec 'Encryption' do |ss| #有几个do就有几个end
  ss.subspec 'RNCryptor' do |sss| #复杂
    sss.source_files = 'DriverRecordSoundKit/Encryption/RNCryptor/*.{h,m}' #指定子模块路径
    end
end
s.subspec 'BaiduComponent' do |f|
  f.source_files = 'MapFundation/Classes/Baidu/**/*.{h,m}'
  f.public_header_files = 'MapFundation/Classes/Baidu/**/*.h'
  
  f.vendored_libraries = 'MapFundation/thirdlibs/*.{a}'
  f.vendored_frameworks = 'MapFundation/frameworks/*.{framework}'
  f.frameworks ='CoreGraphics','CoreLocation','OpenGLES','QuartzCore','Security','SystemConfiguration'
  f.libraries        = 'iconv','sqlite3','c++','z'
  f.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-ObjC' }
  f.dependency 'MapFundation/Common'
end
部署的架构
s.pod_target_xcconfig = { 'VALID_ARCHS' => 'arm64 armv7', 'OTHER_LDFLAGS' => '-force_load'}
s.user_target_xcconfig = { 'VALID_ARCHS' => 'arm64 armv7', 'OTHER_LDFLAGS' => '-force_load'}

c、模仿默认的 podspec 文件生成自己的 podspec 文件
默认的 podspec 文件
Pod::Spec.new do |s|
  s.name             = 'XJPCategoryKit'
  s.version          = '0.1.0'
  s.summary          = 'A short description of XJPCategoryKit.'

# This description is used to generate tags and improve search results.
#   * Think: What does it do? Why did you write it? What is the focus?
#   * Try to keep it short, snappy and to the point.
#   * Write the description between the DESC delimiters below.
#   * Finally, don't worry about the indent, CocoaPods strips it!

  s.description      = <<-DESC
TODO: Add long description of the pod here.
                       DESC

  s.homepage         = 'https://github.com/xiejiapei-creator/XJPCategoryKit'
  # s.screenshots     = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'xiejiapei-creator' => '2170928274@qq.com' }
  s.source           = { :git => 'https://github.com/xiejiapei-creator/XJPCategoryKit.git', :tag => s.version.to_s }
  # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

  s.ios.deployment_target = '8.0'

  s.source_files = 'XJPCategoryKit/Classes/**/*'
  
  # s.resource_bundles = {
  #   'XJPCategoryKit' => ['XJPCategoryKit/Assets/*.png']
  # }

  # s.public_header_files = 'Pod/Classes/**/*.h'
  # s.frameworks = 'UIKit', 'MapKit'
  # s.dependency 'AFNetworking', '~> 2.3'
end
DriverRecordSoundKit 最终的 podspec 文件
Pod::Spec.new do |s|
  s.name             = 'DriverRecordSoundKit'
  s.version          = '1.0.0'
  s.summary          = '使用场景包括:司机行驶过程、会议、课程等的全程录音'
  s.description      = <<-DESC
  1. 部分城市运管部门要求网约车需提供服务过程中录音功能
  2. 与高德等聚合平台对账时,对于部分争议作弊订单,需要行程中录音证据
  3. 司乘发生纠纷时,有行程中录音可方便责任判定,并且行程中录音功能的存在,可在一定程度上避免一些恶意投诉或司机不规范服务
  4. 便于业务部门抽查司机服务规范情况,例如人工抽查或语音质检
  5. 本录音工具类也可用于会议或者上课等场景进行全程录制
                       DESC

  s.homepage         = 'https://github.com/xiejiapei-creator/DriverRecordSoundKit'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'xiejiapei-creator' => '2170928274@qq.com' }
  s.source           = { :git => 'https://github.com/xiejiapei-creator/DriverRecordSoundKit.git', :tag => s.version.to_s }
  s.social_media_url   = "https://www.jianshu.com/u/1ceb4a330607"
  s.ios.deployment_target = '10.0'

  s.source_files = 'DriverRecordSoundKit/Classes/**/*'
  s.public_header_files = 'DriverRecordSoundKit/Classes/UCARRecordSoundTool.h'
  s.vendored_libraries = 'DriverRecordSoundKit/Classes/**/*.a'

  s.frameworks = "AVFoundation", "Foundation", "Security"
  s.dependency 'RNCryptor-objc'

end
XJPCategoryKit 最终的 podspec 文件
Pod::Spec.new do |s|
  s.name             = 'XJPCategoryKit'
  s.version          = '0.1.0'
  s.summary          = '提供便利的分类'
  s.description      = <<-DESC
提供OC常见的各种分类方法
                       DESC

  s.homepage         = 'https://github.com/xiejiapei-creator/XJPCategoryKit'
  s.license          = { :type => 'MIT', :file => 'LICENSE' }
  s.author           = { 'xiejiapei-creator' => '2170928274@qq.com' }
  s.source           = { :git => 'https://github.com/xiejiapei-creator/XJPCategoryKit.git', :tag => s.version.to_s }
  s.social_media_url   = "https://www.jianshu.com/u/1ceb4a330607"

  s.ios.deployment_target = '8.0'

  s.source_files = 'XJPCategoryKit/Classes/**/*'
  s.public_header_files = 'Pod/Classes/XJPCategoryKit.h'

end

d、解决系统库文件不存在报错的问题

首先逐个查找文件,看看依赖了哪些系统的库

#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import "UCARSingle.h"
#include <mach/mach.h> //获取CPU信息所需要引入的头文件

然后将其添加到DriverRecordSoundKit.podspec文件中

s.frameworks = "AVFoundation", "Foundation", "Security","mach"

接着就报错了说是该系统库不存在

ld: framework not found mach
clang: error: linker command failed with exit code 1 (use -v to see invocation)

所以添加到DriverRecordSoundKit.podspec文件中之前需要先去查找下看看该系统库是否存在,如果不存在说明其已经包含在其他系统库文件中了,这里mach库包含在了Foundation库中。

查找系统库

5、更新 GitHub 里面的库

a、依次执行下面命令以关联远程分支
xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % git add .
xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % git commit -m "IOS司机端APP行驶全程录音框架"

// 添加tag标记
xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % git tag 1.0.0 
xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % git push --tag

// 关联远程分支
xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % git remote add origin 'https://github.com/xiejiapei-creator/XJPCategoryKit'

// 得知分支名称为master
xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % git branch -a 
* master

xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % git push origin master

b、验证 podspec 文件是否有效
pod spec lint DriverRecordSoundKit.podspec

如果验证不通过,可以执行pod spec lint DriverRecordSoundKit.podspec --verbose查看详细的ERRORWARING提示,根据提示依次解决相关问题。

pod spec lint DriverRecordSoundKit.podspec --verbose

修改后总是报错,清除缓存或直接删除APP重新执行就OK了,因为使用pod repo push的使用,pod会从缓存中复制工程,然后再编译验证。

pod cache list //查看缓存
pod cache clean --all //清除缓存 

假如出现了无关痛痒的警告,可以直接忽略掉

    - NOTE  | [iOS] xcodebuild:  warning: Skipping code signing because the target does not have an Info.plist file and one is not being generated automatically. (in target 'App' from project 'App')
    - WARN  | [iOS] xcodebuild:  XJPCategoryKit/XJPCategoryKit/Classes/NSDate+Custom.m:70:67: warning: values of type 'NSInteger' should not be used as format arguments; add an explicit cast to 'long' instead [-Wformat]

xiejiapei@xiejiapeis-iMac XJPCategoryKit % pod spec lint XJPCategoryKit.podspec --allow-warnings

最后,终于出现了梦寐以求的成功符号!

Analyzed 1 podspec.

XJPCategoryKit.podspec passed validation.

c、更新版本之前要先删除远程库的 tag 和本地的 tag
// 删除本地tag
xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % git tag -d 1.0.0
Deleted tag '1.0.0' (was 9a60dca)

// 删除远程库tag
xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % git push origin :refs/tags/1.0.0

否则会被拒绝更新

[!] Unable to accept duplicate entry for: XJPCategoryKit (0.1.0)

删除后更新tag再提交就ok了

Downloading dependencies
Installing XJPCategoryKit 1.0.0 (was 0.1.0)

6、提交 .podspec 文件到 CocoaPods

如果是第一次提交,需要先执行下面的命令去CocoaPods注册(填写邮箱,收取验证链接,点击链接,就OK)。

xiejiapei@xiejiapeis-iMac XJPCategoryKit % pod trunk register 2170928274@qq.com '谢佳培' --description='分类方法的库'

Ignoring ffi-1.12.2 because its extensions are not built. Try: gem pristine ffi --version 1.12.2
[!] Please verify the session by clicking the link in the verification email that has been sent to 2170928274@qq.com

然后再执行以下命令。

pod trunk push DriverRecordSoundKit.podspec

[!] The spec did not pass validation, due to 3 warnings (but you can use `--allow-warnings` to ignore them).

如果出现警告的话则使用忽略警告的语法,执行然后大功告成!!!

xiejiapei@xiejiapeis-iMac XJPCategoryKit % pod trunk push XJPCategoryKit.podspec --allow-warnings

Ignoring ffi-1.12.2 because its extensions are not built. Try: gem pristine ffi --version 1.12.2
Updating spec repo `trunk`

CocoaPods 1.10.0 is available.
To update use: `gem install cocoapods`

For more information, see https://blog.cocoapods.org and the CHANGELOG for this version at https://github.com/CocoaPods/CocoaPods/releases/tag/1.10.0

Validating podspec
 🎉  Congrats

 🚀  XJPCategoryKit (0.1.0) successfully published
 📅  November 18th, 21:18
 🌎  https://cocoapods.org/pods/XJPCategoryKit
 👍  Tell your friends!

这时进入到远程仓库,发现没有显示我们提交的文件,而是有个警告框让我们审查一下提交的内容,究其原因是我们在远程仓库中出现了两个分支,一个main分支,另外一个是master分支,而我们目前正处于main分支上,所以显示的内容还是之前的。

远程仓库

为了方便地解决上面提到的问题,我们需要使用Sourcetree工具来管理远程仓库,下面是将远程仓库的url克隆到Sourcetree工具里。

远程仓库的URL
克隆到Sourcetree

Sourcetree工具上将项目从main分支切换到master分支。在远程仓库中不好进行这个操作,而在Sourcetree工具中切换和合并分支的操作却很容易进行。

从main切换到master分支

接下来在Sourcetree工具上删除掉远程仓库中无用的main分支,结果发现出错了。

删除main分支出错

这是因为我们的远程仓库默认的分支仍然是main分支,拒绝删除,所以需要到远程仓库中修改默认分支,修改完毕之后,不要忘记点击旁边的 update 按钮,因为update一下才能生效。

修改默认分支为master

之后就成功删除掉main分支了,再回到github的仓库首页看下,发现我们提交的库出来了,感到到哭😭,我做的第一个库完成了,一路坎坷都是泪。

Github上搜索我们的框架发现也能够成功查找到了哈哈😄。

搜索库

7、使用创建的库

a、安装框架
xiejiapei@xiejiapeis-iMac Example % pod install
Integrating client project
Pod installation complete! There are 3 dependencies from the Podfile and 3 total pods installed.

b、导入框架
#import <XJPCategoryKit.h>

XJPCategoryKit.h文件为提供给外界的公共入口文件,其包括了以下头文件。

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

//! Project version number for XJPCategoryKit.
FOUNDATION_EXPORT double XJPCategoryKitVersionNumber;

//! Project version string for XJPCategoryKit.
FOUNDATION_EXPORT const unsigned char XJPCategoryKitVersionString[];

#import "NSDate+Custom.h"
#import "NSObject+Custom.h"
#import "NSString+Custom.h"
#import "UIColor+Custom.h"
#import "UIImage+Custom.h"
#import "UILabel+Custom.h"
#import "UIScreen+Custom.h"
#import "UITextField+Custom.h"
#import "UIView+Custom.h"
#import "UIViewController+Custom.h"

c、使用框架
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 判断一个字符串是否都是纯数字
    NSString *testString = @"123456";
    if ([testString judgeIsPureInt])
    {
        NSLog(@"该字符串为纯数字,说明生成的库可用");
    }
}

输出结果为:

2020-11-19 15:08:54.798484+0800 XJPCategoryKit_Example[26855:668614] 该字符串为纯数字,说明生成的库可用

搞定!!!


8、创建过程遇到的问题

a、pattern did not match any file
- NOTE  | [iOS] xcodebuild:  DriverRecordSoundKit/DriverRecordSoundKit/RecordSoundKit.h:18:9: fatal error: 'lame.h' file not found
- NOTE  | [iOS] xcodebuild:  DriverRecordSoundKit/DriverRecordSoundKit/AudioTool.m:11:9: fatal error: 'RNCryptor iOS.h' file not found
- ERROR | [iOS] [DriverRecordSoundKit/SupportingFiles] file patterns: The `source_files` pattern did not match any file.
- ERROR | [iOS] file patterns: The `resources` pattern did not match any file.
- ERROR | [iOS] file patterns: The `vendored_libraries` pattern did not match any file.

因为路径设置有误所以找不到文件。经我试验后发现最有效的解决方案就是设置模糊匹配:spec.source_files = 'DriverRecordSoundKit/**/*.{h,m}'。你真要一个个去匹配,你会发现不仅麻烦而且有时候即使你认为路径设置正确了,它也找不到文件.....


b、Prefix.pch
- ERROR | [iOS] unknown: Encountered an unknown error (No such file or directory @ rb_sysopen - /private/var/folders/2j/53b9tdz551l0x8mjtg3zhv4r0000gn/T/CocoaPods-Lint-20201117-15842-kud7vb-DriverRecordSoundKit/Pods/DriverRecordSoundKit/DriverRecordSoundKit/RNCryptor-Prefix.pch) during validation.

目前得出的结论,pchpod库中,完全就是绊脚石般的存在。个人亲测,无论你怎么玩,只要pch存在,就会报这个错误。查看了很多第三方库的pod文件,发现别人压根不使用pch这玩意。


c、missing required architecture i386
- NOTE  | [iOS] xcodebuild:  ld: warning: ignoring file DriverRecordSoundKit/DriverRecordSoundKit/ConvertMP3/libmp3lame.a, missing required architecture i386 in file DriverRecordSoundKit/DriverRecordSoundKit/ConvertMP3/libmp3lame.a (4 slices)

这个就太坑了。眼看离胜利只剩最后一步,你给我报个啥玩意?遍查无解。分析这个错误,缺少了i386架构的东西。查看一下这个框架支持哪些架构,发现确实没有 i386。

xiejiapei@xiejiapeis-iMac DriverRecordSoundKit % lipo -info /Users/xiejiapei/Desktop/DriverRecordSoundKit/DriverRecordSoundKit/SupportingFiles/libmp3lame.a
Architectures in the fat file: /Users/xiejiapei/Desktop/DriverRecordSoundKit/DriverRecordSoundKit/SupportingFiles/libmp3lame.a are: armv7 armv7s x86_64 arm64 

查看这个框架的源文件,发现做了个版本号的判断,低版本生成i386,高版本生成x86_64,所以这个答案是无解的。

PLATFORM="iPhoneSimulator"
if [ "$ARCH" = "x86_64" ]
then
    SIMULATOR="-mios-simulator-version-min=7.0"
            HOST=x86_64-apple-darwin
else
    SIMULATOR="-mios-simulator-version-min=5.0"
            HOST=i386-apple-darwin
fi
i386
x86_64

在网上找到一份支持i386的框架尝试了一下,发现的确出现了 i386 ,但是带入到项目后发现也是无效的,仍然报了之前的错误。不过它只是个警告,就不去管它了,之前以为是它影响到了linker command failed才煞费苦心。

Architectures in the fat file: /Users/xiejiapei/Downloads/libmp3lame/libmp3lame.a are: armv6 armv7 i386 armv7s arm64 
i386

d、Info.plist
- NOTE  | [iOS] xcodebuild:  warning: Skipping code signing because the target does not have an Info.plist file and one is not being generated automatically. (in target 'App' from project 'App')

plist可以作为资源文件保存下来。

spec.resources = "DriverRecordSoundKit/**/*.{plist,modulemap}"

使用方式

NSString *filePath = [[NSBundle bundleForClass:[DriverRecord class]] pathForResource:@"Themes" ofType:@"plist"];
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:filePath];

e、linker command failed
    - ERROR | [iOS] xcodebuild: Returned an unsuccessful exit code. You can use `--verbose` for more information.
    - NOTE  | [iOS] xcodebuild:  clang: error: linker command failed with exit code 1 (use -v to see invocation)
[!] The spec did not pass validation, due to 1 error.

我遇到的玩命的错误,真的解答不出来。不过有几个心得。
1、.a文件的存放位置需要放到Classes文件夹下,放到其他地方不生效。
2、.a文件放入后需要通过pod install安装到项目中,然后再添加到此处

添加.a文件

3、需要添加到DriverRecordSoundKit.podspec文件中,语法比较诡异,你按照目录添加,它却说找不到,还是用模糊匹配吧。添加单个文件的话用的是s.ios.vendored_library,而不是复数那个语法。

  s.ios.vendored_library = 'DriverRecordSoundKit/Classes/**/*.a'

需要把项目中遇到的各种系统库和第三方库全部分离出来进行添加,否则就会出现链接出错的问题。

  s.vendored_libraries = 'DriverRecordSoundKit/Classes/**/*.a'

  s.frameworks = "AVFoundation", "Foundation", "Security"
  s.dependency 'RNCryptor-objc'

四、python3.7

1、安装 python3.7

  1. 网上下载Python 3.7Mac版的安装包,下载后一步步点击下一步进行安装。
  2. 在终端输入open ~/.bash_profile,在文件中添加以下语句配置环境。
export PATH=$PATH:/Library/Frameworks/Python.framework/Versions/3.7/bin/pip3.7
alias pip="/Library/Frameworks/Python.framework/Versions/3.7/bin/pip3.7"
alias python="/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7"
  1. 点击save进行保存,然后关闭弹出的文件。
  2. 在终端继续输入source .bash_profile加载刚才修改过的环境文件。
  3. 输入python查看是否安装成功以及版本号。
Python 3.7.9 (v3.7.9:13c94747c7, Aug 15 2020, 01:31:08) 
Type "help", "copyright", "credits" or "license" for more information.
>>> 
  1. 输入exit()退出版本号查询。
  2. 输入help()查询帮助命令,然后在其中输入module查询已经安装好的模块,通过这个方式可以帮我们排除模块尚未安装的错误。当安装成功后还显示未安装,进入module查询后发现已经存在了,则重启终端即可。

2、使用 python3.7

//运行文件
python3 mainServer.py

//安装缺失模块
pip3 install flask    

3、Mac上Python安装request库老是失败的问题

记录折腾安装request库问题,最终原因是mac上python可以安装多个版本的pythonvs code上使用的默认是最新的,输入python用的是系统默认安装的。

在学习python时,import requests时报错:

ModuleNotFoundError: No module named 'requests’

那我们去安装requests,网上的文档都是pip3 install requests。输入命令后,一直提示:

Defaulting to user installation because normal site-packages is not writeable
Requirement already satisfied: requests in ./Library/Python/3.7/lib/python/site-packages (2.27.1)
Requirement already satisfied: urllib3<1.27,>=1.21.1 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from requests) (1.26.9)
Requirement already satisfied: idna<4,>=2.5 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from requests) (3.3)
Requirement already satisfied: certifi>=2017.4.17 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from requests) (2021.10.8)
Requirement already satisfied: charset-normalizer~=2.0.0 in /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages (from requests) (2.0.12)

提示已经安装了,可是已经安装了为什么import的时候一直提示失败呢。

检查是否已经安装成功request

输入pip3 list,确认也有request。那这到底什么问题呢?是不是和系统的默认安装python冲突了呢,又想着把系统默认的python2.7改为我们用brew新装的python

将homeBrew安装的python3.9设置为默认版本
brew 安装

默认安装了最新版本,最后会在summary中给出安装的地址,比如我的3.9安装在了:/usr/local/xiejiapei/python@3.9/3.9.10

brew install python
打开配置文件并写入python的外部环境变量
open ~/.bash_profile
配置文件中添加
export PATH=${PATH}:/usr/local/xiejiapei/python@3.9/3.9.10/bin
在终端将python重命名
alias python="/usr/local/xiejiapei/python@3.9/3.9.10/bin/3.9”
最后让配置文件生效
source ~/.bash_profile

现在直接用python命令,可以看到已经使用我们安装的3.9了。可是忙活一通发现request还是没有成功。

最后想想是不是pip3和python的路径不一致

输入下面命令,原来有这么多默默的有这么多python版本。其实最终的解决方法是:先看看我们python的位置以及pip3的位置,终端输入命令:which python 。如果你安装的3.9,没有设为默认应该使用which python3.9

这才发现这些版本的路径问题

➜  ~ which python
python: aliased to /usr/local/xiejiapei/python@3.9/3.9.10/bin/python3.9
➜  ~ which python3
/Library/Frameworks/Python.framework/Versions/3.7/bin/python3
➜  ~ which pip3
/Library/Frameworks/Python.framework/Versions/3.7/bin/pip3
➜  ~ which pip3.9
/usr/local/bin/pip3.9

我们brew安装的是3.9,但默认的python3实际对应的是python3.7,我们用pip3安装一直提示已安装,但一直import失败,是因为我们安装的request和使用import不是同一个版本,不在一个路径。所以我们在使用brew安装python之后,查brew list查看我们安装的python的版本,然后使用对应的pip版本来安装request,才会安装在同一路径里。这样在默认python版本中import request库才不会提示错误。比如:默认使用的版本是3.9,即python3.9,那就使用pip3.9 install requests来安装。


参考文献

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容