轉載請註明文章出處: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.
問題截圖:
原因: 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
使用新版代碼並安裝好依賴後,這應該是構建過程中最先出現的問題。
問題截圖:
原因:根據錯誤描述跟蹤腳本執行流程,發現是執行預構建腳本時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
問題截圖:
原因: 子模塊的代碼未下載
解決方案: 初始化子模塊代碼,執行命令: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...
問題截圖:
原因: 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。
問題截圖:
原因: team ID不在已添加的賬號內
解決方案: 在屬性頁面的Team
中選擇自己的賬號
7. Your account does not have sufficient permissions to modify containers. / No profiles for 'xxxx' were found
問題截圖:
原因: 該Bundle ID已經被其他Apple ID使用
解決方案: 換一個新的
8. An Application Group with Identifier 'xxxx' is not available. Please enter a different string.
問題截圖:
原因: 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
問題截圖:
原因: Xcode版本過低,不支持iOS 12.1系統。根據官方頁面,需要Xcode 10
解決方案: 安裝Xcode 10,文件較大,根據網速需要一定時間,請耐心等待
11. Invalid redeclaration of '<-' EnumOprators.swift
問題截圖:
原因: ObjectMapper
的版本過低
解決辦法: 使用新版的ObjectMapper
:打開Podfile
,將ObjectMapper
那一行改成pod 'AlamofireObjectMapper', '~> 5.0'
備註: 解決方案參考https://stackoverflow.com/que...
12. Type 'RLMIterator<proxy>' does not conform to protocol 'Sequence'</proxy>
問題截圖:
原因: 這個問題不清楚具體原因。懷疑是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]'
問題截圖:
原因: 非nil值不應該使用if let
(我自己的理解,畢竟不懂Swift)
解決辦法: 將Potatso/Core/API.swift
第65和256行的if
和大括號去掉,65行修改示意:
<pre>// 修改前
</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)
備註: 解決辦法的靈感來自:https://stackoverflow.com/que...。當然這個問題和Potatso無關。
還有一個錯誤截圖:
具體什麼忘了。如果你遇到了或者有解決方案,可留言告訴我。