在開發(fā)一個新的App時不僅要考慮當前版本的需求,更要考慮到后期的版本迭代和維護工作 《Clean Code》一書中也提出代碼大部分時候是用來維護的,而不是用來實現(xiàn)功能的。所以在前期的框架設(shè)計,技術(shù)調(diào)查上應(yīng)該慎之又慎。本次我將從個人開發(fā)者角度圍繞著代碼的可維護性、可測試性、可復(fù)用性來實現(xiàn)一個簡單的聊天App。
下面是部分界面的展示:
界面展示請點擊: Github RPChat Wiki: 基于MVVM構(gòu)建聊天App
1、基本設(shè)置
新建一個工程,命名為RPChat,此處開發(fā)語言選擇Swift:
(1)、在工程中設(shè)置Info.plist中設(shè)置Allow Arbitrary Loads為YES,參考:stackoverflow Transport security has blocked a cleartext HTTP
(2)、打開Assets.xcassets按照指定的圖片大小添加App的Logo圖片。
2、工程結(jié)構(gòu)
添加三個framework分別命名為RPChat_iOS、RPChatUIKit、RPChatDataKit
- RPChat_iOS是和UI的顯示以及交互相關(guān)的代碼
- RPChatUIKit是整個項目中會用到的對UIKit的公共擴展
- RPChatDataKit是整個項目的數(shù)據(jù)存儲以及訪問接口,也可以理解為是App的View Model以及Model
3、使用carthage管理第三方開源庫
1、carthage 命令
carthage version
cd /Users/****/Desktop/GitHub/RPChat
touch Cartfile
使用VSCode打開Cartfile文件,輸入用到的第三方開源庫:
github "Alamofire/Alamofire" // Http請求封裝
github "ReactiveX/RxSwift" // 用于管理App中的事件
github "onevcat/Kingfisher" // 用于App中的緩存和下載圖片
github "SwiftyJSON/SwiftyJSON" // 生成Model
gitHub "CoderMJLee/MJRefresh" // UItableView下拉組件
github "robbiehanson/CocoaAsyncSocket"
執(zhí)行更新命令:
carthage update --platform iOS --no-use-binaries
2、Using Carthage with Xcode 12
升級Xcode 12后,執(zhí)行上面的命令可能會報錯,解決方法可參考:
Using Carthage with Xcode 12
然后使用以下命令執(zhí)行carthage更新:
carthage.sh bootstrap --platform iOS --cache-builds
更新完成后,打開工程,選擇TARGETS -->Build Phases--> Link Binary With Libries 點擊加號,選擇 Add File --> Carthage --> Build --> iOS 添加所需的FrameWork,
下面的gif演示了如何添加第三方的FrameWork;
接下來,點擊+,選擇New Run Script Phase,此時新建了Run Script,在執(zhí)行命令中添加:
/usr/local/bin/Carthage copy-frameworks
3、解決The file couldn’t be saved.報錯
添加完后再次build可能會報錯:the file couldn’t be saved. command phasescriptexecution failed with a nonzero exit code
解決方案參考:carthage copy-frameworks produces "The file couldn’t be saved." error #3056
Add to run scripts
rm -rf ${TMPDIR}/TemporaryItems/*carthage*
/usr/local/bin/carthage copy-frameworks
再次build成功。
在Input Files中引入我們要用到的庫的路徑:
$(SRCROOT)/Carthage/Build/iOS/Alamofire.framework
其作用是把Carthage引入的第三方庫在打包的時候,拷貝到特定目錄。
在上傳到git倉庫時,不需要傳Carthage下的文件,所以選擇忽略,在.gitignore文件中添加
*.DS_Store
Carthage/
xcuserdata/
.idea/
4、兼容iOS 13之前的老版本
修改最低支持版本為iOS 11
此時發(fā)現(xiàn)再Build工程,發(fā)現(xiàn)已經(jīng)有很多Error,這是版本兼容的問題,由于Xcode 11新建的工程默認為當前最高版本,Xcode新增了一個SceneDelegate文件,具體作用請參考官方文檔:Optimizing App Launch。現(xiàn)在要在AppDelegate和中SceneDelegate做兼容老版本處理。 方法就是對當前系統(tǒng)做一個判斷,然后再根據(jù)不同系統(tǒng)版本分開處理。
在SceneDelegate直接加上@available(iOS 13.0, *)即可,
在AppDelegate做擴展處理:
代碼如下:
@available(iOS 13.0, *)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
}
@available(iOS 13.0, *)
extension AppDelegate {
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}
}
5、國際化
1、常用文案國際化
- 1、如下圖所示: 創(chuàng)建所需國際化的語言,此處我創(chuàng)建了英語、繁體漢語、簡體漢語:
- 2、在工程中新建一個
String File文件,命名為Localizable
點擊到Localizable.strings文件,點擊右側(cè)Localize...按鈕添加需要國際化的語言。
此時來做個測試,在ViewController新建一個名為testLab的UILabel;
@IBOutlet weak var testLab: UILabel!
展開Localize.strings文件,在英文中添加test;,在簡體中文中添加:
"test" = "測試";
在ViewController中調(diào)用,
testLab.text = NSLocalizedString("test", comment: "")
此時點擊Run可以看到testLab顯示內(nèi)容為test;
修改模擬器語言為簡體漢語,再次運行:
2、App名稱國際化
(1)、同樣的方法新建一個名為
InfoPlist的String文件。-
(2)、在
InfoPlist.strings(English)文件中添加:CFBundleName = "CatchU"; -
(3)、在
InfoPlist.strings(Chinese,Simplified)中添加CFBundleName = "暢聊吧"; (4)、 打開
Info.Plist設(shè)置Bundle name屬性為$CFBundleName
- (5)、再次運行代碼,可以看到,App的名稱已經(jīng)修改成功了。
本篇主要講了App的新建和相關(guān)配置,包括:
- 新建工程,基本配置
- 通過三個
frameworks去實現(xiàn)App不同層次的功能 - 通過
Carthage管理工程中用的第三方開源庫 - 對iOS 13之前的系統(tǒng)做一個兼容處理
- 國際化相關(guān)