Xcode beta with CocoaPods

Xcode 10 beta 的 Swift 版本為 4.2,而若你目前所使用的 Pods 多數為 Swift 4 的話,該怎麼辦呢?

你可以在 Podfile 裏頭加上全域的參數來規範所有 Pods 的 Swift version:

post_install do |installer|
    installer.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
            config.build_settings['SWIFT_VERSION'] = '4'
        end
    end
end

如此一番便可以輕鬆地在 Pods 還沒全面支援 Swift 4.2 時就可以使用 Xcode 10 Beta 開發👏

CompactMap vs flatMap

直接從 code 來看兩者之間和 map 的差異

CompactMap

let scores = ["1", "2", "3", "four", "5"]

let mapped: [Int?] = scores.map { str in Int(str) }

// [1, 2, 3, nil, 5] 

let compactMapped: [Int] = scores.compactMap { str in Int(str) }

// [1, 2, 3, 5]

flatMap

let users = [User(name: "Archie", scores: [1, 2, 4]), User(name: "ArchieChang", scores: [3,2,5])]

let mapped = users.map { $0.scores }

// [[1, 2, 4], [3, 2, 5]]

let flatMapped = users.flatMap { $0.scores }

// [1, 2, 4, 3, 2, 5]

在使用情境上,CompactMap 可以將 nil 給過濾掉,使得回傳的陣列為 non optional 的型態;

原先還在使用 map + filter 來處理 nil 的部分,可以直接使用 CompactMap 處理,減少多一次的陣列迴圈。

而 flatMap 則是在將所有陣列的內容整合進同一個陣列,如我們需要計算全體使用者的總得分時,便可以先將個別使用者的分數集結成一個陣列來處理。

UserDefaults with Structure

有時候我們會將一些用戶資訊存在 UserDefaults 裡頭,是個方便且直覺的存取方式。

而 UserDefaults 並非是所有型別都可以接受,如你自己建構的 struct 或 class,

就需要先轉成 Data 的格式來存取。

這邊就來介紹如何存取 User 這個 struct:

struct User {
    var ID: String
    var name: String
    var email: String?
}

這是一個簡單的 User structure,若要轉成 Data 的話,得先將 User 宣告成 Codable,

這樣就可以透過 PropertyListEncoder 和 PropertyListDecoder 來處理 User 和 Data 之間的 encode decode。

而最近喜歡使用 extension 的方式來處理 UserDefaults:

extension UserDefaults {
    var user: User? {
        get {
            guard let data = data(forKey: #function) else { return nil }
            return try? PropertyListDecoder().decode(Profile.self, from: data)
        }
        set {
            if let profile = newValue {
                set(try? PropertyListEncoder().encode(profile), forKey: #function)
            } else {
                set(nil, forKey: #function)
            }
        }
    }
}

我們利用 #function 的特性,將 function name (user) 直接作為 UserDefaults 的 key,

再加上一些判斷是否為 nil 的處理,便可以輕鬆底使用 UserDefaults 存取我們所定義的 structure。

存取 UserDefaults 裡頭的 User 就可以變成很單純的 get 和 set:

// get user from UserDefaults

let user = UserDefaults.standard.user

// set user

UserDefaults.standard.user = user

Git LFS ( Large File Storage )

今天在更新 BlayPods 時,發現 Realm 的某個檔案(60.04 MB)超出了 GitHub 的上限(50.00 MB),所以無法順利地將檔案推上去 GitHub,而 Git 也自行 untracked 那個檔案,所以在 git status 上便失去了蹤影。

至於為什麼會將 Pods 的檔案全推到 GitHub 上呢?

而在 git push 的時候,有顯示解決的方法,便是今天的主題:

Git LFS

首先我們透過 brew 來安裝 git lfs

brew install git-lfs

接著繼續在 git 裡頭安裝

git lfs install

再來我們就來定義哪些檔案需要被 lfs track,像我這邊是這樣:

git lfs track 'Pods/Realm/core/librealmcore-ios.a'

然後可以透過指令來確認是否有被加入到 track 的名單

git lfs track

git status

現在就可以從 git status 之中再次看到剛剛沒推成功的檔案被 track 了!

git lfs track 的內容會被記錄到 .gitattributes 裡頭,所以也一併推上 GitHub 即可完成!

git push

這樣便可以在 GitHub 上處理單個檔案超過 50.00 MB 的問題,不過免費流量為 1GB / month。

 

DeviceSupport

每當 iOS Beta 更新時,原先的 Xcode  便會無法支援,需要透過從 Xcode Beta 的 DeviceSupport 複製新的版本到正式版之中才能使用;

反正都會做這件事,不如就將 Xcode Beta 裡頭的 DeviceSupport 上傳到 GitHub 上提供給 iOS 有更新,但還沒下載新的 Xcode Beta 的人使用吧!

傳送門點我

ignore Pods warning

在使用 CocoaPods 的時候難免會碰上 warning,原因不外乎就是使用的套件本身在 build 的時候所產生的警告,但不建議直接 unlock Pods 去修改,請以那專案修改,並在處理完後發送 Pull Request 造福大眾。

不過現階段來說,我們可以做的事情是忽略 Pods 的 Warning,

只要在 Podfile 裡頭加上

inhibit_all_warnings!

即可在目前的專案中忽略 Pods 相關的 warning。