How to Automatically Create an Initializer for a Swift Class

How to automatically create an initializer for a Swift class?

Update As of Xcode 11.4

You can refactor (right-click mouse menu) to generate the memberwise initializer for class and struct.

Note that struct automatic initializers are internal. You may want to generate memberwise initializer when defining a module to make it public.

Right-click > Refactor > 'Generate Memberwise Initializer'

xcode generate memberwise initialization

For older Xcode

There are handy plugins:

https://github.com/rjoudrey/swift-init-generator https://github.com/Bouke/SwiftInitializerGenerator

Preferred way to initialize a class in Swift

“If a property always takes the same initial value, provide a default value rather than setting a value within an initializer. The end result is the same, but the default value ties the property’s initialization more closely to its declaration. It makes for shorter, clearer initializers and enables you to infer the type of the property from its default value. The default value also makes it easier for you to take advantage of default initializers and initializer inheritance, as described later in this chapter.”

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l

How do I initialize a class over the course of several view controllers

You can't initialize a class over time. You can set an instance's properties over time. That being the case, what you're doing seems fine.
However, alternatively you could keep calling into a builder that creates the Event fully formed only when all the needed info has been provided. Imagine an architecture like this (try it out in your playground):

class Event : CustomStringConvertible {
let fee : String
let fi : String
let fo : String
let fum : String
init(fee:String, fi:String, fo:String, fum:String) {
self.fee = fee; self.fi = fi; self.fo = fo; self.fum = fum
}
var description : String {
"Event: \(fee) \(fi) \(fo) \(fum)"
}
}

class EventBuilder {
private var fee : String?
private var fi : String?
private var fo : String?
private var fum : String?
private var event : Event?
private func makeEventIfPossible() {
guard event == nil else {return}
if let fee = fee,
let fi = fi,
let fo = fo,
let fum = fum {
print("making event")
self.event = Event(fee: fee, fi: fi, fo: fo, fum: fum)
}
}
func takeFee(_ fee:String) {
self.fee = fee
makeEventIfPossible()
}
func takeFi(_ fi:String) {
self.fi = fi
makeEventIfPossible()
}
func takeFo(_ fo:String) {
self.fo = fo
makeEventIfPossible()
}
func takeFum(_ fum:String) {
self.fum = fum
makeEventIfPossible()
}
func giveEvent() -> Event? {
self.event
}
}

let b = EventBuilder()
b.takeFee("Fee")
b.takeFi("Fi")
b.takeFo("Fo")
b.takeFum("Fum")
if let event = b.giveEvent() {
print(event) // and away we go
}

You can pass the EventBuilder around, different objects can call different take methods, and no one can get the Event with giveEvent until all the info has been supplied and the Event has been created. As you can see, the Event is created just once, and none of its properties are Optional. The builder hides the whole creation process behind a functional representation (hence the name).

I can imagine further refinements, like you could make the take methods throws methods where they would refuse to accept a value if that value had already been set, and so on. Also I think you might use keypaths somehow to make the code neater/smaller.

What's init used for in swift?

init is used to set initial values for properties on a struct or class type at the time it is created, before any other methods may be called on it and before it is passed as a parameter to other functions or methods.

In Swift, any non-optional properties must be set with initial values before init returns. Properties may be declared with initial values already, which excludes them from having to be set in an init method.

  • class types must have an init method implemented if there are any non-optional properties not already declared with initial values.

  • For struct types only, Swift will automatically generate an init method with parameters for each non-optional property that was not already declared with an initial value. You can optionally create any number of alternative init methods for the struct, as long as by the time each one returns, all non-optional properties have a value.

  • In your example, there is no difference between the init method created on the second line, and the automatically created init method provided for that struct type by Swift. But you could create alternate initializers that, for example, take a Double instead of an Int and then convert it internally before setting the mark property.

I think the key point to realize is that even when you do not specify an init method yourself, one still exists, as created automatically by Swift for struct types. So in both line one and line two of your example, an init method is being called (and they are essentially identical implementations). The only difference is that you wrote the init implementation in the second line, and the Swift compiler writes the init method in the first line.

deinitonly exists for class types, which are passed by reference and have memory management. Any deinit method you declare on a class you create will be called when there are no more references to that instance of the class and it will be released from memory. It's used to deregister from various observation patterns or otherwise clean up right before the instance is destroyed.

initialize class method for classes in Swift?

If you have an Objective-C class, it's easiest to just override +initialize. However, make sure subclasses of your class also override +initialize or else your class's +initialize may get called more than once! If you want, you can use dispatch_once() (mentioned below) to safeguard against multiple calls.

class MyView : UIView {
override class func initialize () {
// Do stuff
}
}

 

If you have a Swift class, the best you can get is dispatch_once() inside the init() statement.

private var once = dispatch_once_t()

class MyObject {
init () {
dispatch_once(&once) {
// Do stuff
}
}
}

This solution differs from +initialize (which is called the first time an Objective-C class is messaged) and thus isn't a true answer to the question. But it works good enough, IMO.

How can I make the memberwise initialiser public, by default, for structs in Swift?

Quoting the manual:

"Default Memberwise Initializers for Structure Types
The default memberwise initializer for a structure type is considered private if any of the structure’s stored properties are private. Otherwise, the initializer has an access level of internal.

As with the default initializer above, if you want a public structure type to be initializable with a memberwise initializer when used in another module, you must provide a public memberwise initializer yourself as part of the type’s definition."

Excerpt from "The Swift Programming Language", section "Access Control".

No need for initializer for optional properties inside Swift class

Optional Property Types :

If your custom type has a stored property that is logically allowed to have “no value”—perhaps because its value cannot be set during initialization, or because it is allowed to have “no value” at some later point—declare the property with an optional type. Properties of optional type are automatically initialized with a value of nil, indicating that the property is deliberately intended to have “no value yet” during initialization.

For Example :

class SurveyQuestion {
var text: String?
init(text: String) {
self.text = text
}
func ask() {
print(text)
}
}

let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?")
cheeseQuestion.ask()
// Prints "Do you like cheese?"
let cheeseQuestion1 = SurveyQuestion()
cheeseQuestion.ask()
// Prints nil


Related Topics



Leave a reply



Submit