再次回到makeRoundedRectangleMaker:
func makeRoundedRectangleMaker(sz:CGSize) -> -> UIImage { return { imageOfSize(sz) { let p = UIBezierPath( roundedRect: CGRect(origin:CGPointZero, size:sz), cornerRadius: 8) p.stroke } } }
我對上述方法的一個地方不太滿意:它所創建的圓角矩形的尺寸是個參數(sz),不過圓角矩形的cornerRadius卻是硬編碼的8,我希望能夠為圓角半徑指定值。有兩種方式可以做到這一點。一種是為makeRoundedRectangleMaker本身再提供一個參數:
func makeRoundedRectangleMaker(sz:CGSize, _ r:CGFloat) -> -> UIImage { return { imageOfSize(sz) { let p = UIBezierPath( roundedRect: CGRect(origin:CGPointZero, size:sz), cornerRadius: r) p.stroke } } }
然後像下面這樣調用:
let maker = makeRoundedRectangleMaker(CGSizeMake(45,20), 8)
還有另外一種方式。現在,makeRoundedRectangleMaker所返回的函數不接收參數,我們可以讓它接收一個參數:
func makeRoundedRectangleMaker(sz:CGSize) -> (CGFloat) -> UIImage { return { r in imageOfSize(sz) { let p = UIBezierPath( roundedRect: CGRect(origin:CGPointZero, size:sz), cornerRadius: r) p.stroke } } }
現在,makeRoundedRectangleMaker所返回的函數會接收一個參數,因此在調用時需要將這個參數提供給它:
let maker = makeRoundedRectangleMaker(CGSizeMake(45,20)) self.myImageView.image = maker(8)
如果不需要保存maker供其他地方使用,那就可以在一行完成所有這些事情:函數調用會生成一個函數,我們再立刻調用該函數來獲取圖片:
self.myImageView.image = makeRoundedRectangleMaker(CGSizeMake(45,20))(8)
如果函數返回的函數接收一個參數,就像該示例這樣,那麼它就叫作柯裡化函數(為了紀念計算機科學家Haskell Curry)。Swift提供了柯裡化函數的便捷聲明方式;可以省略第1個箭頭運算符與頂層匿名函數,如以下代碼所示:
func makeRoundedRectangleMaker(sz:CGSize)(_ r:CGFloat) -> UIImage { return imageOfSize(sz) { let p = UIBezierPath( roundedRect: CGRect(origin:CGPointZero, size:sz), cornerRadius: r) p.stroke } }
表達式(sz:CGSize)(_r:CGFloat)(一行有兩個參數列表,並且中間沒有箭頭運算符)表示「Swift,請對該函數進行柯裡化」。Swift會將函數劃分到兩個函數中,一個是makeRoundedRectangleMaker,接收CGSize參數,另一個是匿名函數,接收CGFloat。代碼看起來好像是makeRoundedRectangleMaker會返回一個UIImage,不過實際上它返回的是一個函數,該函數會返回一個UIImage,就像之前那樣。我們可以像之前所採用的兩種方式那樣調用它。