Edited at

Swiftでメソッドチェーンを実装する

More than 3 years have passed since last update.

パラメータを渡すといい感じに処理してくれるようなコードを書こうとすると、結構な数のパラメータが必要な場合があるかと思います。

単純に必要な数だけ引数を用意してもいいのですが、一度にすべての引数を使わない場合や、ライブラリとして公開する場合などは、もう少しスマートに対応したいところです。

そんな場合の対応方法のひとつとして、メソッドチェーンにて設定できるようにする方法があるかと思います。


サンプル

UIViewを作成するサンプルです。


呼び出し側のコード

ViewBuilder(parent: view)

.setFrame(CGRect(x: 50, y: 50, width: 100, height: 100))
.setBackgroundColor(UIColor.green())
.setBorderColor(UIColor.lightGray())
.setBorderWidth(4.0)
.setCornerRadius(14.0)
.build()

実行するとこうなります。

screen.png



実装側のコード

import UIKit

public class ViewBuilder {
private var parentView: UIView
private var frameRect: CGRect?
private var backgroundColor: UIColor?
private var borderColor: UIColor?
private var borderWidth: CGFloat?
private var cornerRadius: CGFloat?

public init(parent: UIView) {
self.parentView = parent
}

public func setFrame(_ frameRect: CGRect) -> Self {
self.frameRect = frameRect
return self
}

public func setBackgroundColor(_ backgroundColor: UIColor) -> Self {
self.backgroundColor = backgroundColor
return self
}

public func setBorderColor(_ borderColor: UIColor) -> Self {
self.borderColor = borderColor
return self
}

public func setBorderWidth(_ borderWidth: CGFloat) -> Self {
self.borderWidth = borderWidth
return self
}

public func setCornerRadius(_ cornerRadius: CGFloat) -> Self {
self.cornerRadius = cornerRadius
return self
}

public func build() {
let view = UIView()

if let frameRect = frameRect {
view.frame = frameRect
}

if let backgroundColor = backgroundColor {
view.backgroundColor = backgroundColor
}

if let borderColor = borderColor {
view.layer.borderColor = borderColor.cgColor
}

if let borderWidth = borderWidth {
view.layer.borderWidth = borderWidth
}

if let cornerRadius = cornerRadius {
view.layer.cornerRadius = cornerRadius
}

parentView.addSubview(view)
}
}


  • 設定値を保持するプロパティを用意

  • 設定値を受け取るメソッドを用意

  • チェーンできるように設定値を保持しつつ、自身を返却

  • 終端メソッドにて、存在するパラメータを設定

みたいに実装すれば良いかと!