Swift is now open source. For the latest news, visit the Swift open source blog

Failable Initializers

Swift version 1.1 is new in Xcode 6.1, and it introduces a new feature: failable initializers. Initialization is the process of providing initial values to each of the stored properties of a class or struct, establishing the invariants of the object. In some cases initialization can fail. For example, initializing the object requires access to a resource, such as loading an image from a file:

NSImage(contentsOfFile: "swift.png")

If the file does not exist or is unreadable for any reason, the initialization of the NSImage will fail. With Swift version 1.1, such failures can be reported using a failable initializer. When constructing an object using a failable initializer, the result is an optional that either contains the object (when the initialization succeeded) or contains nil (when the initialization failed). Therefore, the initialization above should handle the optional result directly:

if let image = NSImage(contentsOfFile: "swift.png") {
	// loaded the image successfully
} else {
	// could not load the image
}

An initializer defined with init can be made failable by adding a ? or a ! after the init, which indicates the form of optional that will be produced by constructing an object with that initializer. For example, one could add a failable initializer to Int that attempts to perform a conversion from a String:

extension Int {
	init?(fromString: String) { 
		if let i = fromString.toInt() {
			// Initialize
			self = i
		} else { 
			// return nil, discarding self is implied
			return nil
		}
	}
}

In a failable initializer, return nil indicates that initialization has failed; no other value can be returned. In the example, failure occurs when the string could not be parsed as an integer. Otherwise, self is initialized to the parsed value.

Failable initializers eliminate the most common reason for factory methods in Swift, which were previously the only way to report failure when constructing this object. For example, enums that have a raw type provided a factory method fromRaw that returned an optional enum. Now, the Swift compiler synthesizes a failable initializer that takes a raw value and attempts to map it to one of the enum cases. For example:

enum Color : Int {
	case Red = 0, Green = 1, Blue = 2

	// implicitly synthesized
	var rawValue: Int { /* returns raw value for current case */ }

	// implicitly synthesized
	init?(rawValue: Int) {
		switch rawValue { 
			case 0: self = .Red
			case 1: self = .Green
			case 2: self = .Blue
			default: return nil
		}
	}
}

Using the failable initializer allows greater use of Swift’s uniform construction syntax, which simplifies the language by eliminating the confusion and duplication between initializers and factory methods. Along with the introduction of failable initializers, Swift now treats more Cocoa factory methods — those with NSError arguments — as initializers, providing a more uniform experience for object construction.

You can read more about failable initializers in The Swift Programming Language.

All Blog Posts