FLAnimatedImage - GIF 圖片最佳實踐
GIF 圖片在 Web 時代是一種廣泛使用的圖片格式。 但在 iOS 中,原生庫直到現在也沒有提供對 GIF 比較完善的支持。 FLAnimatedImage 這個庫正式專門為 iOS App 中顯示 GIF 圖片而來的。
FLAnimatedImage 簡介
FLAnimatedImage 是 Flipboard 團隊開發的在它們 App 中渲染 GIF 圖片使用的庫。 后來 Flipboard 將 FLAnimatedImage 開源出來供大家使用。 所以你不用擔心它在實踐中會不會出現問題, 畢竟已經在 Flipboard 這種 App 上面經過充分的實踐驗證了。
因為 Flipboard App 中很多頻道會展示大量的 GIF 圖片,而 iOS 原生的系統庫中并沒有提供對 GIF 很好的支持,所以 FLAnimatedImage 就應運而生了。
基本思路
大家如果在 iOS 中處理過 GIF 圖片, 如果通過原生系統提供的能力, 可能只有兩種方式。 并且這兩種方式都不是專門針對于 GIF 的解決方案,更像是一種 hack。
第一種方式, UIImage 雖然提供了一種創建連續切換的動畫圖片的能力, 但這個能力更像是為了那些簡單動畫而服務的。 比如加載數據時候顯示的 loading 圖片。 如果將 GIF 圖片通過這種能力來顯示,會帶來諸多問題。
第二種方式,可能是大家用的最多的了。 就是創建一個 UIWebView 然后在這里面把 GIF 顯示出來。 但從原理上來想, UIWebView 并不是為了顯示 GIF 圖片而生的。 其實也算不上最佳實踐。
但 iOS 原生系統庫目前只提供了這幾個能力, 用這些 hack 方式也是無奈之舉。
使用 FLAnimatedImage
給大家介紹了基本的問題背景, 咱們就來看看 FLAnimatedImage 是如何解決這個問題的吧。 我們可以通過Carthage 將 FLAnimatedImage 集成進來, 創建這樣一個 Cartfile :
github "Flipboard/FLAnimatedImage"
然后執行:
carthage update
就可以將 FLAnimatedImage 拉取下來。
如果你使用的 Swift 可以在 Bridgeing Header 中引入 FLAnimatedImage :
#import <FLAnimatedImage/FLAnimatedImage.h>
隨后在需要的地方這樣調用 FLAnimatedImage 就可以了:
//創建 FLAnimatedImageView
let imageView = FLAnimatedImageView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
self.view.addSubview(imageView)
let imageURLString = "https://media.giphy.com/media/Nm8ZPAGOwZUQM/giphy.gif"
if let imageURL = URL(string: imageURLString) {
//讀取圖片
let session = URLSession(configuration: URLSessionConfiguration.default)
session.dataTask(with: imageURL, completionHandler: { (data, response, error) in
if data != nil {
let image = FLAnimatedImage(animatedGIFData: data)
imageView.animatedImage = image
}
}).resume()
}
這里給大家簡單講解一下, 首先我們初始化一個 FLAnimatedImageView 實例。 然后 URLSession 讀取圖片數據, 得到圖片的數據 data 后, 用這個數據初始化 FLAnimatedImage 實例, 最后將它設置給 animatedImage 屬性。 這樣就完成了, 其余的 GIF 渲染工作都由 FLAnimatedImage 來處理。
上面的代碼應該比較簡明易懂,如果有疑問可以在留言中提出~
GIF 渲染原理
為什么說 FLAnimatedImage 相對于 iOS 原生的幾種 hack 方式更趨近于最佳實踐呢? 咱們簡單聊聊 FLAnimatedImage 渲染 GIF 圖片的原理。 FLAnimatedImage 會有兩個線程同時在運轉。 其中一個線程負責渲染 GIF 的每一幀的圖片內容(所謂的渲染,大體上就是加載 GIF 文件數據,然后抽取出來當前需要哪一幀)。這個加載圖片的過程是在異步線程進行的。
然后 FLAnimatedImage 會有一個內存區域專門放置這些渲染好的幀。 這時候,在主線程中的 ImageView 會根據當前需要,從這個內存區域中讀取相應的幀。這是一個典型的 生產者-消費者 問題。
這樣最大限度的保證主線程不去處理圖片渲染的操作,并且我們剛才說的那個內存區域, 也是經過一系列的動態管理,以提升性能。 并且 FLAnimatedImage 的渲染線程,在數據沒有準備好的時候,不會加鎖等待,而是直接返回 nil。 這樣也能避免一些實現中為了圖片序列完全顯示正確,而造成性能卡頓的問題。
結語
FLAnimatedImage 提供了一種更好的 GIF 圖片渲染實踐。 下次如果你的項目中需要使用 GIF 圖片的時候,就可以考慮使用 FLAnimatedImage 來操作, 而不是用 UIWebView 費時費力的 hack 了。 大家如果有一些建議,或是更好的實踐,也非常歡迎在留言中一起討論。
來自:http://www.swiftcafe.io/2016/12/08/fl-image/