Default Initializer in swift
Chances are it's an issue with the Swift compiler and access control (not pointing fingers, just trying to troubleshoot). Add an explicit initializer to the class and see if that works:
class ShoppingListItem {
var name: String?
var quantity = 1
var purchased = false
init() { }
}
If that doesn't work, then set the class to public, along with the initializer
public class ShoppingListItem {
var name: String?
var quantity = 1
var purchased = false
public init() { }
}
Swift how to make the default initializer of a `struct` private
If you are noticing that implementing:
struct Foo {
let bar: String
static let sharedInstance = Foo(bar: "blah")
}
is legal even without giving bar
an initial value, why? because Swift Structs have a default initializer, called the memberwise initializer:
Structure types automatically receive a memberwise initializer if they
do not define any of their own custom initializers. Unlike a default
initializer, the structure receives a memberwise initializer even if
it has stored properties that do not have default values.The memberwise initializer is a shorthand way to initialize the member
properties of new structure instances. Initial values for the
properties of the new instance can be passed to the memberwise
initializer by name.
Meaning that if you tried to create a new instance of Foo
struct, the compiler should -automatically- provide:
However, you can get rid of it by implementing private init()
, but you have to make sure that all stored properties have -dummy- initial values (or maybe let them optionals...) because the struct no longer has an initializer for guaranteeing that the stored properties has values.
It should be similar to:
struct Foo {
var bar: String = ""
static var shared = Foo()
private init() {}
}
Remark: I would suggest to stuck with class when implementing a singleton pattern, you might want to check this answer (Thanks to
MartinR for mentioning it).
Codable default values during initialization
Once you conform to Encodable
, it's as if your class has explicitly declared a encode(to:)
method and a init(from:)
initialiser.
By declaring an initialiser with arguments, you immediately lose the default (parameterless) initialiser that the compiler generates for you when all properties have a default value. This is why you can't do KillSwitches()
. This is stated in the documentation:
Swift provides a default initializer for any structure or class that
provides default values for all of its properties and does not provide
at least one initializer itself. The default initializer simply
creates a new instance with all of its properties set to their default
values.
KillSwitches
has a init(from:)
initialiser already, so Swift doesn't provide the default initialiser.
You just have to add the parameterless initialiser in yourself:
class KillSwitches: Codable {
public enum CodingKeys: String, CodingKey {
case featureOne
case featureTwo
case featureThree
}
let featureOne: Bool = true
let featureTwo: Bool = true
let featureThree: Bool = false
init() { }
}
And then you can do:
let defaultKillSwitches = KillSwitches()
if you want the default values.
How to pass default value when initializing a struct in swift
You have to give all of the properties a valid before you can call methods. I would refactor your init
to something like this:
init(header: String?, errorLocation: String?, userID: String?, description: String, errorMessage: String) {
self.header = header ?? " ::Error::"
self.errorLocation = errorLocation ?? ""
self.userID = userID ?? ""
self.description = " ::description::" + description
self.errorMessage = " ::errorMessage::" + errorMessage
if errorLocation == nil {
self.errorLocation = getErrorLocation()
}
if userID == nil {
self.userID = getUserID()
}
}
That will fix the "self used before all stored properties are initialized" error.
To use default values, update the signature:
init(header: String? = nil, errorLocation: String? = nil, userID: String? = nil, description: String, errorMessage: String) {
// nothing else changes
}
Now you can call the initializer without the nil
parameters.
For example:
let logError = LogError(header: nil, errorLocation: nil, userID: nil, description: "An error occurred while verifying if the user profile exists", errorMessage: "\(error?.localizedDescription ?? "")")
becomes:
let logError = LogError(description: "An error occurred while verifying if the user profile exists", errorMessage: "\(error?.localizedDescription ?? "")")
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
iOS custom init issue, how to set the default init method?
Remove the other init that you implemented and set yours as required
class CustomLabel: UILabel {
required init(_ title: String = "Star"){
super.init(frame: CGRect.zero)
text = title
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
let label1 = CustomLabel()
print(label1)
This works and uses the expected init
EDIT:
Bastian provided a useful link in their answer but has since removed it.
The link: Adding Swift Convenience Initializers
Useful snippet from link (in case the link ever breaks):
Designated or Convenience?
First a recap on the two types of initializer:
A designated initializer is the primary initializer for a class. It
must fully initialize all properties introduced by its class before
calling a superclass initializer. A class can have more than one
designated initializer.A convenience initializer is a secondary initializer that must call a
designated initializer of the same class. It is useful when you want
to provide default values or other custom setup. A class does not
require convenience initializers.The Three rules
With that clear you need to remember three rules for designated and
convenience initializers for class types:
- A designated initializer must call a designated initializer from the
immediate superclass.- A convenience initializer must call another
initializer from the same class.- A convenience initializer must
ultimately call a designated initializer.
What does this mean for us?
In simple terms, do not call super from your convenience initializer.
Call another initializer (convenience or designated) from the same
class.
Optional and default values need to be initialized with default initializer
You can define an initializer with default values for some params
struct Token {
var a: Int
var b: Int
var c: Int?
init(a: Int, b: Int = -1, c: Int? = nil) {
self.a = a
self.b = b
self.c = c
}
}
Now you can create a Token in several ways
Token(a: 1) // (1, -1, nil)
Token(a: 1, b: 2) // (1, 2, nil)
Token(a: 1, c: 3) // (1, -1, 3)
Token(a: 1, b: 2, c: 3) // (1, 2, 3)
Usually is a good practice writing the default value of a property on the same line where it is defined (as you did). I moved the default value of
b
from it's definition to theinit
just to make this example shorter.
Related Topics
How to Get the Yaw, Pitch, Roll of an Aranchor in Absolute Terms
What's the Best Approach to Prefill Core Data Store When Using Nspersistentcloudkitcontainer
Guarantees About the Lifetime of a Reference in a Local Variable
Rxswift: Observable While a Button Holds Down
Uitableviewcell Asynchronously Loading Images Issue - Swift
Trying to Use Keychainitemwrapper by Apple "Translated" to Swift
Vapor 3 Beta Example Endpoint Request
iOS - Arkit Node Disappear After 100M
Create PDF of Dynamic Size with Typography Using Uiview Template(S)
Scenekit Object Between Two Points
How to Subclass Custom Uiviewcontroller in Swift
Select Next Nstextfield with Tab Key in Swift
Cannot Assign to Property: 'Self' Is Immutable, I Know How to Fix But Needs Understanding
Using Just with Flatmap Produce Failure Mismatch. Combine