共计 7178 个字符,预计需要花费 18 分钟才能阅读完成。
转载请注明文章出处:https://tlanyan.me/build-pota…
前言
半年前写过一篇构建自用 Shadowsocks 客户端 Potatso 的教程“构建自己的 iOS 网络代理客户端”。当时除 libYAML 依赖下载不正常外,编译测试使用全过程都很顺利。文章投递到几个平台被数万网友围观,不少网友根据教程在构建时遇到各种问题。最初我以为是网友看教程不仔细或构建环境差异造成,没多注意。后来陆续有网友加我 QQ,让我怀疑写完文章后代码有了重大更新。
终于在昨天(除夕)抽出时间,用最新版的代码构建 Potatso 并安装到我最新版 iOS 系统的 iPad 上。这个过程花费了几个小时,覆盖了许多网友咨询我的问题,本文中将一一给出解决方案。
如果你的 Xcode 版本是 9.4.1,使用 commitID 为 318a5e1 的代码,根据“构建自己的 iOS 网络代理客户端”中的教程可以顺利的编译和安装 Potatso 到 iOS12 系统以下的设备。如果你的设备升级到了最新版,或者遇到其他问题,请继续阅读本文。
为什么执着于构建自用 Shadowsocks 客户端?由于 iOS 生态的封闭性,正常情况下只能通过 App Store 下载应用。应用下架后,会导致手机重置、购买买新设备后无法安装。安卓、Windows、MacOS 则不会有这个问题,只要安装文件存在,总是有得用。所以针对 iOS 设备构建自用的客户端很有必要,尤其是 SS 这类随时有可能下架的应用。
本文构建 Potatso 客户端最终得工程文件以及生成的 ipa 包已上传到百度云盘:https://pan.baidu.com/s/1twyM… 如果构建过程中遇到本文列出以外的问题,欢迎留言或加 Q 群 688196496。
构建步骤
这节简要回顾构建 Potatso 的流程:
1. 安装 Cocospods
如果已安装,请略过此步。
更新系统的 gem 版本:打开终端,输入:sudo gem update –system;
设置国内 gem 源:gem sources –list 输出为 https://gems.ruby-china.org/ 请略过此步;否则先删除官方源再添加 gems 国内源:gem sources –remove https://rubygems.org/; gem sources –add https://gems.ruby-china.org/;
安装 Cocospods:sudo gem install cocoapods。
2. 构建 Potatso
构建 Potatso 的步骤如下:
克隆代码:git clone https://github.com/haxpor/Potatso.git;
更新子模块:cd Potatso; git submodule update –init;
安装依赖:打开 Podfile,将第一行改成:source ‘https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git’(使用清华的 CocoaPods 源),然后运行 pod install –verbose;
使用 XCode 打开 Potatso.xcworkspace;
更改 Potatso 及 PacketTunnel、TodayWidget 两个子项目的 Bundle ID,例如本人分别改成:potatso.tlanyan.me、potatso.tlanyan.me.PacketTunnel 和 potatso.tlanyan.me.TodayWidget;
更改 Potatso 及 PacketTunnel、TodayWidget 两个子项目 Capabilities 中的 App Group 和 Keychain Sharing 的 Group: 在 ”App Groups” 中删除原有的 group.io.wasin.potatso,新增自己的 group,例如:”group.potatso.tlanyan.me”;在 ”Keychain Sharing” 中输入自己的 group ID;
打开 ”PotatsoBase/Potatso.m” 文件,将 shareGroupIdentifier 函数的返回值改成自己的 group id;
将 iPhone 等 iOS 设备连接到电脑,目标选择新接入的设备,点击左上角的“build and run”按钮,Xcode 会编译并安装 App 到设备上,然后启动。
可能遇到的问题
昨天几个小时的折腾,遇到的十来个问题。下文将一一列出,并给出解决方案。构建过程中你可能会遇到不止一个错误,请根据错误信息按 Ctrl + F 在本文查找。如果遇到其他问题,欢迎留言或加 Q 群 688196496。
1. the sandbox is not in sync with the Podfile.lock. Run ‘pod install’ or update your CocosPods installation.
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”842″ height=”206″ class=”aligncenter size-full wp-image-3193″ />
原因:pod 依赖未安装
解决办法:安装依赖,执行命令:pod install –verbose
2. url: (7) Failed to connect to pyyaml.org port 80: Connection refused
错误描述:执行 pod install,前面一切顺利,到 libYAML 会出现问题:
Installing LibYAML (0.1.4)
[!] Error installing LibYAML
[!] /usr/bin/curl -f -L -o /var/folders/dj/ljst94xx47l7fn3wz4q9bwsw0000gn/T/d20180822-4467-1cotycr/file.tgz http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz –create-dirs –netrc-optional –retry 2
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 –:–:– –:–:– –:–:– 0
curl: (7) Failed to connect to pyyaml.org port 80: Connection refused
原因:libYAML 的官网关闭了 80 端口访问
解决办法:编辑 ” /Users/ 你的用户名 /.cocoapods/repos/master/Specs/5/b/9/LibYAML/0.1.4/LibYAML.podspec.json” 文件,将 ”http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gz” 改成“https://pyyaml.org/download/l…”
备注:此解决方案来自貌似 LibYAML 官方人员的回复,亲测可以。当然可以使用前文“构建自己的 iOS 网络代理客户端”中所说的网络劫持方法。
3. Diff:/Podfile.lock: No such file or directory
使用新版代码并安装好依赖后,这应该是构建过程中最先出现的问题。
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”854″ height=”246″ class=”aligncenter size-full wp-image-3192″ />
原因:根据错误描述跟踪脚本执行流程,发现是执行预构建脚本时 SRCROOT 环境变量的值无法获取 (或被错误置为空) 导致。
解决方案: 尝试过更改构建时生成的临时脚本文件、注入全局环境变量等,这些方法均不凑效。后来通过 diff 发现脚本由文件 Potatso.xcodeproj/project.pbxproj 文件中的配置生成,该文件在 pod install 后被修改。解决办法很简单:还原更改。执行完 pod install 命令后,执行 git checkout Potatso.xcodeproj/project.pbxproj,问题解决。
4. No podspec found for CallbackURLKit in ./Library/CallbackURLKit
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”665″ height=”93″ class=”aligncenter size-large wp-image-3194″ />
原因:子模块的代码未下载
解决方案:初始化子模块代码,执行命令:git submodule update –init
5. The operation couldn’t be completed. Unable to log in with account ‘xxxx’. The login details for account ‘xxxx’ / No profiles for ‘xxxx’ were found: Xcode couldn’t find any iOS App Development provisioning profiles matching ‘xxx’ / Code signing is required for product type…
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”855″ height=”221″ class=”aligncenter size-full wp-image-3195″ />
原因:Apple ID 过期未续费
解决方案:Apple ID 续费或换其他可用的 ID
6. No account for team ‘xxx’. Add a new account in the Accounts preference pane or verify that your accounts have valid…
错误信息基本与上一条相同,只是账号换成了 team ID。
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”878″ height=”214″ class=”aligncenter size-full wp-image-3198″ />
原因:team ID 不在已添加的账号内
解决方案:在属性页面的 Team 中选择自己的账号
7. Your account does not have sufficient permissions to modify containers. / No profiles for ‘xxxx’ were found
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”380″ height=”149″ class=”aligncenter size-full wp-image-3196″ />
原因:该 Bundle ID 已经被其他 Apple ID 使用
解决方案:换一个新的
8. An Application Group with Identifier ‘xxxx’ is not available. Please enter a different string.
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”493″ height=”197″ class=”aligncenter size-full wp-image-3197″ />
原因:Group ID 已经被其他 Apple ID 使用
解决方案:用一个新的
9. Module ‘Crashlytics’ not found
这个错误未截图。
原因:Podfile 文件里没有加这个库
解决方案:打开 Podfile,在 def library 中添加一行:pod ‘Crashlytics’, ‘~> 3.10.7’,然后执行 pod install –verbose。
备注:该解决方案参考 Github 的 issue: https://github.com/haxpor/Pot…。注意 pod 安装依赖后,会更改 Potatso.xcodeproj/project.pbxproj 文件,直接编译会出现第二个问题。正确操作应当如下:先备份 Potatso.xcodeproj/project.pbxproj 文件,然后执行 pod install –verbose,成功后将文件覆盖。后续出现 pod 依赖更新的情况也应该按此步骤操作。
10. Could not locate device support files
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”412″ height=”148″ class=”aligncenter size-full wp-image-3199″ />
原因:Xcode 版本过低,不支持 iOS 12.1 系统。根据官方页面,需要 Xcode 10
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”888″ height=”493″ class=”aligncenter size-full wp-image-3200″ />
解决方案:安装 Xcode 10,文件较大,根据网速需要一定时间,请耐心等待
11. Invalid redeclaration of ‘<-‘ EnumOprators.swift
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”294″ height=”619″ class=”aligncenter size-full wp-image-3201″ />
原因:ObjectMapper 的版本过低
解决办法:使用新版的 ObjectMapper:打开 Podfile,将 ObjectMapper 那一行改成 pod ‘AlamofireObjectMapper’, ‘~> 5.0’
备注:解决方案参考 https://stackoverflow.com/que…
12. Type ‘RLMIterator<proxy>’ does not conform to protocol ‘Sequence'</proxy>
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”283″ height=”379″ class=”aligncenter size-full wp-image-3203″ />
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”665″ height=”264″ class=”aligncenter size-large wp-image-3204″ />
原因:这个问题不清楚具体原因。怀疑是 Realm 这个库的问题,没有实现 Sequence 接口。我将 RealmSwift 改到最新的 3.7.6 问题亦没有解决。不懂 Swift,不过感觉是 RMLIterator 或者 Proxy/RuleSet 等存在问题。
解决办法:注销 PotatsoMode/DBUtils.swift 中的相关代码,具体是 174-190 和 202-218 行之间的代码。
备注:解决方案来自:https://github.com/haxpor/Pot…。所有错误中,只有这个错误不是完美解决。
13. Initializer for conditional binding must have Optional type, not ‘[Rule]’
问题截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”379″ height=”151″ class=”aligncenter size-full wp-image-3205″ />
原因:非 nil 值不应该使用 if let(我自己的理解,毕竟不懂 Swift)
解决办法:将 Potatso/Core/API.swift 第 65 和 256 行的 if 和大括号去掉,65 行修改示意:
<pre>// 修改前 // if let parsedObject = Mapper<Rule>().mapArray(JSONArray: rulesJSON as! [[String : Any]]){// let parsedObject = Mapper<Rule>().mapArray(JSONArray: rulesJSON as! [[String : Any]])// rules.append(contentsOf: parsedObject)//}// 修改后 let parsedObject = Mapper<Rule>().mapArray(JSONArray: rulesJSON as! [[String : Any]])rules.append(contentsOf: parsedObject)</pre>
备注:解决办法的灵感来自:https://stackoverflow.com/que…。当然这个问题和 Potatso 无关。
还有一个错误截图:
<img src=”https://tlanyan.me/wp-content…; alt=”” width=”766″ height=”661″ class=”aligncenter size-full wp-image-3202″ />
具体什么忘了。如果你遇到了或者有解决方案,可留言告诉我。
参考
构建自己的 iOS 网络代理客户端