class init - blky/IOS-Swift GitHub Wiki

apple docs on this topis

default initializer

Swift provides a default initializer for any structure or base class that provides default values for all of its properties and does not provide at least one initializer itself.

Swift defines two kinds of initializers for class types to help ensure all stored properties receive an initial value. These are known as designated initializers and convenience initializers.

Designated initializers

are the primary initializers for a class. A designated initializer fully initializes all properties introduced by that class and calls an appropriate superclass initializer to continue the initialization process up the superclass chain.

  • Classes tend to have very few designated initializers, and it is quite common for a class to have only one. Every class must have at least one designated initializer.
  • In some cases, this requirement is satisfied by inheriting one or more designated initializers from a superclass,

image Convenience initializers

  • are secondary, supporting initializers for a class.
  • You can define a convenience initializer to call a designated initializer from the same class as the convenience initializer with some of the designated initializer’s parameters set to default values.
    class Food {
    var name: String
    init(name: String) {
    self.name = name
    }
    convenience init() {
    self.init(name: "[Unnamed]")
    }
    }
  • You can also define a convenience initializer to create an instance of that class for a specific use case or input value type.
convenience init(parameters) {

        statements

    }
  • A simple way to remember this is:
    Designated initializers must always delegate up.
    Convenience initializers must always delegate across.

Swift’s two-phase initialization process

In the first phase, each stored property is assigned an initial value by the class that introduced it. Once the initial state for every stored property has been determined, the second phase begins, and each class is given the opportunity to customize its stored properties further before the new instance is considered ready for use.

  • is similar to initialization in Objective-C.

  • The main difference is that during phase 1, Objective-C assigns zero or null values (such as 0 or nil) to every property.

  • Swift’s initialization flow is more flexible in that it lets you set custom initial values, and can cope with types for which 0 or nil is not a valid default value.

    • Properties can only be accessed, and methods can only be called, once the class instance is known to be valid at the end of the first phase.
    • if you write a subclass initializer that matches a superclass convenience initializer, that superclass convenience initializer can never be called directly by your subclass,
    • You always write the override modifier when overriding a superclass designated initializer, even if your subclass’s implementation of the initializer is a convenience initializer.
  • Subclasses can modify inherited variable properties during initialization, but can not modify inherited constant properties

Failable Initializers

  • It is sometimes useful to define a class, structure, or enumeration for which initialization can fail.
  • You write a failable initializer by placing a question mark after the init keyword (init?).
    struct Animal {
	    let species: String
	    init?(species: String) {
	    if species.isEmpty { return nil }
	    self.species = species
	    }
    }

    let anonymousCreature = Animal(species: "")
	    // anonymousCreature is of type Animal?, not Animal
	    if anonymousCreature == nil {
	    println("The anonymous creature could not be initialized")
	    }
	    // prints "The anonymous creature could not be initialized"

    }

another example



    class CartItem: Product {
	    let quantity: Int!
	    init?(name: String, quantity: Int) {
	    super.init(name: name)
	    if quantity < 1 { return nil }
	    self.quantity = quantity
    }
    }

You can override a superclass failable initializer in a subclass, just like any other initializer. Alternatively, you can override a superclass failable initializer with a subclass non-failable initializer. This enables you to define a subclass for which initialization cannot fail, even though initialization of the superclass is allowed to fail.

  • You can override a failable initializer with a nonfailable initializer but not the other way around.

The example below defines a class called Document. This class models a document that can be be initialized with a name property that is either a non-empty string value or nil, but cannot be an empty string:



    class Document {
	    var name: String?
	    // this initializer creates a document with a nil name value
	    init() {}
	    // this initializer creates a document with a non-empty name value
	    init?(name: String) {
	    if name.isEmpty { return nil }
	    self.name = name
	    }
    }



The next example defines a subclass of Document called AutomaticallyNamedDocument. The AutomaticallyNamedDocument subclass overrides both of the designated initializers introduced by Document. These overrides ensure that an AutomaticallyNamedDocument instance has an initial name value of "[Untitled]" if the instance is initialized without a name, or if an empty string is passed to the init(name:) initializer:



    class AutomaticallyNamedDocument: Document {
	    override init() {
		    super.init()
		    self.name = "[Untitled]"
		    }
		    override init(name: String) {
		    super.init()
		    if name.isEmpty {
		    self.name = "[Untitled]"
		    } else {
		    self.name = name
	    }
	    }
    }


Failable Initializers for Enumerations

    enum TemperatureUnit {
   
    case Kelvin, Celsius, Fahrenheit
    
	   init?(symbol: Character) {
		   switch symbol {
		   case "K":
		   	self = .Kelvin
		   case "C":
		   	self = .Celsius
		   case "F":
		   	self = .Fahrenheit
		   default:
		   	return nil
	   }
    }

what is property!

an implicitly unwrapped integer type (Int!). this means that the property has a default value of nil before it is assigned a specific value during initialization.

Required Initializers

Write the required modifier before the definition of a class initializer to indicate that every subclass of the class must implement that initializer:

	class SomeClass {
	    required init() {
	    // initializer implementation goes here
	    }
    }

⚠️ **GitHub.com Fallback** ⚠️