3

I would like to apply DRY to the lines I'm creating in swift. How can I refactor this code so a closure is called? It resides on a viewcontroller.

var topLineView: UIView = {
    let lineView = UIView()
    lineView.layer.borderWidth = 1.0
    lineView.layer.borderColor = UIColor.lightGray.cgColor
    return lineView
}()

var bottomLineView: UIView = {
    let lineView = UIView()
    lineView.layer.borderWidth = 1.0
    lineView.layer.borderColor = UIColor.lightGray.cgColor
    return lineView
}()

var centerLineView: UIView = {
    let lineView = UIView()
    lineView.layer.borderWidth = 1.0
    lineView.layer.borderColor = UIColor.lightGray.cgColor
    return lineView
}()

I tried creating a variable but that caused an error:

let lineView = {
    let lineView = UIView()
    lineView.layer.borderWidth = 1.0
    lineView.layer.borderColor = UIColor.lightGray.cgColor
    return lineView
}

var centerLineView = lineView()

error (Unable to infer closure type etc...)

Rik
  • 1,870
  • 3
  • 22
  • 35

2 Answers2

4

Swift isn't able to infer the return type of your closure, so you need to tell it ahead of time that you are returning a UIView. This compiles and runs fine.

let lineView = { () -> UIView in
    let lineView = UIView()
    lineView.layer.borderWidth = 1.0
    lineView.layer.borderColor = UIColor.lightGray.cgColor
    return lineView
}
var myViewFromClosure = lineView()
var myViewFromClosure2 = lineView()
var myViewFromClosure3 = lineView()

I personally would opt for a function instead of a closure in this case, however. Like this:

func lineViewFunc() -> UIView {
    let lineView = UIView()
    lineView.layer.borderWidth = 1.0
    lineView.layer.borderColor = UIColor.lightGray.cgColor
    return lineView
}

var myViewFromFunc = lineViewFunc()
var myViewFromFunc2 = lineViewFunc()
var myViewFromFunc3 = lineViewFunc()
joehinkle11
  • 491
  • 1
  • 4
  • 9
  • Definitely agree about the function. It's worth remembering that a function can be locally nested inside another function, and that makes a nice way to extract locally repeated code without polluting the outer namespace. – Rob Napier Oct 22 '19 at 19:30
  • I tried a function but the complier complains that self is not initialized – Rik Oct 22 '19 at 22:42
  • @Rik you can share your implementation if you’d like – joehinkle11 Oct 22 '19 at 22:44
  • I ended up creating a separate class because a function would not work but also repeating myself in a similar situation because my manager said to use a function also but then I would have to make it optional – Rik Oct 23 '19 at 15:09
  • I guess I could just create an empty and use a method to configure it in viewdidload... – Rik Oct 23 '19 at 15:11
  • @Rik I added a function example in my answer – joehinkle11 Oct 23 '19 at 15:20
  • Also, it ultimately really doesn't matter if you're using a `function` or a `closure`. Related: https://stackoverflow.com/questions/24108667/what-is-the-difference-between-functions-and-closures – joehinkle11 Oct 23 '19 at 15:28
0

The issue with a function is I have to call it before super.init, but self does not exist yet.

Rik
  • 1,870
  • 3
  • 22
  • 35