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'
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 aninit
method implemented if there are any non-optional properties not already declared with initial values.For
struct
types only, Swift will automatically generate aninit
method with parameters for each non-optional property that was not already declared with an initial value. You can optionally create any number of alternativeinit
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 createdinit
method provided for thatstruct
type by Swift. But you could create alternate initializers that, for example, take aDouble
instead of anInt
and then convert it internally before setting themark
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.
deinit
only 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
Swift Core Data Sync with Web Server
How to Get User Data from Facebook Sdk on iOS
How to Cache Images Only in Disk Using Kingfisher
Openurl in Appdelegate Conversion Error Nsstring -> String (Swift & iOS8)
Shift Avplayer Captions When Subview Overlaps Them
Display UI (Storyboard Possibly) with Broadcast UI Extension
Uidocumentinteractioncontroller() Swift
Uitableview Height Does Not Change Dynamically in Swift iOS
Gmsmarker Icon in the Top Left Corner of the View (Ios)
Setting Custom Http Headers in Alamofire in iOS 7 Not Working
iOS Swift3 Check Nil Value for Viewcontroller Object
Use More Than One Firebase Database in Single App - Swift
How to Eliminate the Margin on the Left Side of a Uitableview, Without Creating a Gap on the Right
Simplest Way to Implement a "Read More" Button to Expand a Uitextview in iOS Swift 2
In iOS Avplayer, Addperiodictimeobserverforinterval Seems to Be Missing