轉載請註明文章出處:tlanyan.me/build-potat…
前言
半年前寫過一篇構建自用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包已上傳到百度雲盤:pan.baidu.com/s/1twyMocOv…
如果構建過程中遇到本文列出以外的問題,歡迎留言或加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"檔案,將"pyyaml.org/download/li…"改成“pyyaml.org/download/li…
備註: 此解決方案來自貌似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: github.com/haxpor/Pota…。注意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'
備註: 解決方案參考stackoverflow.com/questions/5…
12. Type 'RLMIterator' does not conform to protocol 'Sequence'
問題截圖:
原因: 這個問題不清楚具體原因。懷疑是Realm
這個庫的問題,沒有實現Sequence
介面。我將RealmSwift
改到最新的3.7.6問題亦沒有解決。不懂Swift,不過感覺是RMLIterator
或者Proxy/RuleSet等存在問題。
解決辦法: 登出PotatsoMode/DBUtils.swift
中的相關程式碼,具體是174-190和202-218行之間的程式碼。
備註: 解決方案來自:github.com/haxpor/Pota…。所有錯誤中,只有這個錯誤不是完美解決。
13. Initializer for conditional binding must have Optional type, not '[Rule]'
問題截圖:
原因: 非nil值不應該使用if let
(我自己的理解,畢竟不懂Swift)
解決辦法: 將Potatso/Core/API.swift
第65和256行的if
和大括號去掉,65行修改示意:
// 修改前
// 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)
複製程式碼
備註: 解決辦法的靈感來自:stackoverflow.com/questions/3…。當然這個問題和Potatso無關。
還有一個錯誤截圖:
具體什麼忘了。如果你遇到了或者有解決方案,可留言告訴我。