Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplifying initializers #60

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

simplifying initializers #60

wants to merge 1 commit into from

Conversation

carlos-chaguendo
Copy link

@devxoul What do you think of this syntax?

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

    let label = UILabel {
        $0.textAlignment = .center
        $0.textColor = .black
        $0.text = "Hello, World!"
    }
@devxoul
Copy link
Owner

devxoul commented Jun 29, 2018

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

@carlos-chaguendo
Copy link
Author

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.

@devxoul
Copy link
Owner

devxoul commented Jul 1, 2018

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?

@carlos-chaguendo
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants