【iOS開發】初識函式式Swift實用

KyXu發表於2016-04-29

Swift 的語言特性使得它非常適合被用於以函數語言程式設計思想,如果你還沒開始用函式式的方式來使用它,那麼可以從現在開始,嘗試著利用函式式的便利性。

let indicateView = UIImageView(frame: view.frame)
indicateView.image = UIImage(named: "how2use")
self.view.addSubview(indicateView)

我剛剛寫了上面這段程式碼,來讓我的當前頁面顯示名為 “how2use” 的這張圖片。看起來好像是我做了三件事:

  • 根據 frame 建立 UIImageView
  • 根據圖片名稱配置 UIImageView
  • 將 UIImageView 作為 subview 傳給其他 view

但是實際上,我只需要 frame、imageName 這兩個東西就可以把這三行程式碼配置好,或者說我能不能用這兩個引數來把上面的三行程式碼縮減為一行。

extension UIImageView {
    
    func frameSelf (rect:CGRect) -> UIImageView {
        self.frame = rect
        return self
    }
    
    func imageSelf (imageName:String) -> UIImageView {
        self.image = UIImage(named: imageName)
        return self
    }

    func placeSelf (view:UIView) -> UIImageView {
        view.addSubview(self)
        return self
    }
}

寫了上面這些方法之後,程式碼修改成這個樣子了:

let indicateView = UIImageView()
        .frameSelf(view.frame)
        .imageSelf("how2use")
        .placeSelf(self.view)

為了程式碼可讀性,這裡我寫了四行,但顯然這是一行程式碼。
繼而我發現 indicateView 這個名字沒有存在的必要,於是我廢棄掉 placeSelf 這個方法,改成這樣:

self.view.addSubview(UIImageView()
    .frameSelf(view.frame)
    .imageSelf("how2use"))

一行程式碼,不引入多餘的變數。
如果你願意的話,這個模式還可以繼續寫下去。

extension UIImageView {
    
    func tagSelf (tag:Int) -> UIImageView {
        self.tag = tag
        return self
    }
    
    func modeSelf(contentMode:UIViewContentMode) -> UIImageView {
        self.contentMode = contentMode
        return self
    }
}

最後程式碼會變成這種形式:

NSObject().func1().func2().func3()......

思考

  1. 上面這些程式碼的優勢在於:類似 indicateView 這種東西,用一次就不要了,沒必要引入新的名稱,不便於理解和記憶,我們就可以函式式地把它解決掉,程式碼更精簡易讀。
  2. 上面我用了 xxxxSelf 這種方式來表明,這種方法不是用一下就完了,它會返回這個物件本身,所以你還可以繼續做別的事情。但是這種命名方式我個人看來不夠好,唯一好的地方可能只是在於:本來我想設定 imageView.tag = 100,結果敲出 tag 這三個字母,Xcode 就提示我有 tagSelf 這個方法可以用,這可以讓我方便地自動補全這個方法,不需要記憶方法名。
  3. 這種程式設計方式的優點之一在於不同方法之間的組合性,如果你想把上面這些方法整合到一個函式裡,然後通過傳一大堆的引數來進行呼叫,是畫蛇添足。
  4. 顯然這種方式有其弊端,不宜濫用,而且修改程式碼的時候要注意:假如你要改動 func2,注意它和 func1、func3 之間是不是存在什麼先後關係。特別是你用這種方式來給圖片做濾鏡處理的時候,一張圖片先高斯模糊再打馬賽克,先打馬賽克再高斯模糊是完全不同的。
userImage.blur().mosaic() // 馬賽克本身是清晰的
userImage.mosaic().blur() // 馬賽克本身是模糊的

推薦一下個人部落格:kyxu.tech


相關文章