Is There No Default(T) in Swift

Is there no default(T) in Swift?

There isn't. Swift forces you to specify the default value, just like then you handle variables and fields. The only case where Swift has a concept of default value is for optional types, where it's nil (Optional.None).

Can I assign a default type to generic type T in Swift?

There's no support for default generic arguments, but you can fake it by defining the default init() on a type-constrained extension, in which case the compiler will be smart enough to use that type. E.g.:

class MyManager<T> {
let instance: T

init(instance: T) {
self.instance = instance
}
}

extension MyManager where T == NSObject {
convenience init() {
self.init(instance: NSObject())
}
}

And now you can initialize the type with no argument and it will default to MyManager<NSObject>:

let mm1 = MyManager(instance: "Foo") // MyManager<String>
let mm2 = MyManager(instance: 1) // MyManager<Int>
let mm3 = MyManager() // MyManager<NSObject>

SwiftUI uses this technique quite a lot.

In swift, when one property has no default value, the default values held by other properties become useless?

From The Swift Programming Language

Structure types automatically receive a memberwise initializer if they
do not define any of their own custom initializers. This is true even
if the structure’s stored properties 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.

As you haven't declared any initialisers for your struct, the only initialiser that is available is the memberwise initialiser.

You can declare an initialiser that just takes a name in order to use the default value for nose. This then requires you to explicitly declare the memberwise initialiser -

struct Person {
var name: String
var nose: Int = 1

init(_ name:String) {
self.name=name;
}

init (name:String, nose:Int){
self.name=name;
self.nose=nose;
}
}

var mike = Person(name: "mike", nose: 1)
var john = Person("john")

Providing a default value for an Optional in Swift?

Update

Apple has now added a coalescing operator:

var unwrappedValue = optionalValue ?? defaultValue

The ternary operator is your friend in this case

var unwrappedValue = optionalValue ? optionalValue! : defaultValue

You could also provide your own extension for the Optional enum:

extension Optional {
func or(defaultValue: T) -> T {
switch(self) {
case .None:
return defaultValue
case .Some(let value):
return value
}
}
}

Then you can just do:

optionalValue.or(defaultValue)

However, I recommend sticking to the ternary operator as other developers will understand that much more quickly without having to investigate the or method

Note: I started a module to add common helpers like this or on Optional to swift.

Swift generics with default value

Swift 3 added generic type aliases. These might help you avoid typing all types each time.

Example:

typealias AnyResult<E> = CallbackResult<Any, E>
typealias AnyCallback<E> = (AnyResult<E>) -> ()

func foo(callback: AnyCallback<String>?) {
callback?(.failure(error: "Ouch!"))
}

foo() { result in
if result.isSuccess {
// ...
}
}

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 add default implementation using generic protocol extension?

Maybe this would be simpler.

extension Comparable {
func limit(from minValue: Self, to maxValue: Self) -> Self {
return Swift.max(Swift.min(self, maxValue), minValue)
}
}

How to disable default nil-initialization of Optional

If your var's type is written T? with no default value, and Swift synthesizes a memberwise init for your type, then the synthesized init uses a default value of nil for that var.

However, if your var's type is written Optional<T> with no default value, then the synthesized init does not use a default value.

So write this instead:

struct DataOne {
let id: String
var name: Optional<String>
// ...
}

struct DataTwo {
let id: String
var name: Optional<String>
// ...
}

Or write out your init instead of letting the compiler synthesize it:

struct DataOne {
let id: String
var name: String?

init(id: String, name: String?) {
self.id = id
self.name = name
}
}

struct DataTwo {
let id: String
var name: String?

init(id: String, name: String?) {
self.id = id
self.name = name
}
}

You can use Xcode's Editor > Refactor > Generate Memberwise Initializer command to write most of the init for you, then delete the = nil default:

demonstration of using Generate Memberwise Initializer



Related Topics



Leave a reply



Submit