Then icon indicating copy to clipboard operation
Then copied to clipboard

simplifying initializers

Open carlos-chaguendo opened this issue 6 years ago • 4 comments

@devxoul What do you think of this syntax?

   let label = UILabel {
        $0.textAlignment = .center
        $0.textColor = .black
        $0.text = "Hello, World!"
   }

carlos-chaguendo avatar Jun 28 '18 22:06 carlos-chaguendo

I don't think it works for some classes that take parameters.

devxoul avatar Jun 29 '18 04:06 devxoul

That's true, but for classes that don't need parameters it's very useful, keeping in mind that many times we can omit those parameters and set them in the code block

    let label = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 20)).then {
        $0.textAlignment = .center
        $0.textColor = .black
        $0.text = "Hello, World!"
    }

equals to

    let label = UILabel {
        $0.frame = CGRect(x: 0, y: 0, width: 100, height: 20)
        $0.textAlignment = .center
        $0.textColor = .black
        $0.text = "Hello, World!"
    }

I think the second option is easier to understand.

carlos-chaguendo avatar Jun 29 '18 13:06 carlos-chaguendo

I'm worried about adding a custom initializer to existing types. I found there is a crash when using a custom NSObject subclass that doesn't implement init().

import Foundation

protocol Then {}
extension NSObject: Then {}

extension Then where Self: NSObject {
  init(block: (Self) -> Void) {
    self.init()
    block(self)
  }
}

class Foo: NSObject {
  var name: String?

  init(handler: () -> Void) {
    super.init()
  }
}

// Fatal error: Use of unimplemented initializer 'init()' for class '__lldb_expr_2.Foo'
let foo = Foo {
  $0.name = ""
}

The compiler cannot ensure that we're not using the safe initializer. Do you have an idea?

devxoul avatar Jul 01 '18 03:07 devxoul

https://docs.swift.org/swift-book/LanguageGuide/Initialization.html

Subclasses do not inherit their superclass initializers by default. However, superclass initializers are automatically inherited if certain conditions are met.

Rule 1 If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers.

Rule 2 If your subclass provides an implementation of all of its superclass designated initializers—either by inheriting them as per rule 1, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initializers.

These rules apply even if your subclass adds further convenience initializers.

your error is caused by creating an initializer


class Foo: NSObject {
    
    init(handler: () -> Void) {
        super.init()
    }
}

// the initializer `init()`  was not inherited  *Rule1*
Foo.init()

That said, it can be assumed that the correct implementation is:

class Foo: NSObject {
    var name: String?
    
    override init() {
        super.init()
    }
    
    init(handler: () -> Void) {
        super.init()
    }
}

In my opinion, this type of case should be specified in the documentation of Then

carlos-chaguendo avatar Jul 03 '18 12:07 carlos-chaguendo