How to Initialize a Struct with a Closure Parameter Like This

How can you initialize a struct with a closure parameter like this?

This works just like any function whose last parameter is a function. Trailing closure syntax is trailing closure syntax. The fact that the function is an initializer changes nothing.

So let me build up to it in stages. You know you can say:

func myfunc(whatever: () -> ()) {}
myfunc {}

Okay, but now let's make it a static method:

struct S {
static func myfunc(whatever: () -> ()) {}
}
S.myfunc {}

OK, but init is a static method — it's just a static method whose name you are allowed to omit:

struct S {
let whatever: () -> ()
}
S {} // meaning S.init {}

How to create a struct parameter that is a closure with input, returning `some View` instead of `AnyView` in SwiftUI?

You just need to make ReusableView generic and declare the return type of your closure as the generic type.

struct ReusableView<Output: View>: View {
let outputView: (String) -> Output

var body: some View {
outputView("Hello World")
}
}

struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ReusableView() {
CustomViewA($0)
}
}
}

Initialize struct with fields using closure

'structs without named fields' aren't exactly structs but tuple structs. Whereas the name of a tuple struct can be used the same way as a function name, it isn't true for a struct name. Using the struct name to instantiate one struct, you have to specify the name of the parameters:

println!("{:?}", wrap(1, |i|(D { x: i }))); // doesn't sound good, but works

Uncertain of this Swift struct syntax with closure

The declaration for the Effect type

struct Effect<T> {

Defines Effect as using a Generic type T. So you can create Effect objects that work on different types.

The line

let anIntInTwoSeconds = Effect<Int> { callback in

Creates an Effect object that operates on Ints, and assigns it to the variable anIntInTwoSeconds.

The { callback in part defines the closure for the Effect object. That declaration could be rewritten like this:

let anIntInTwoSeconds = Effect<Int>(run: { callback in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
callback(42)
}
}
)

You can interpret as:

'Create an instance of the Effect struct, with a run property that contains the closure that begins with "{ callback in"...'

(It's confusing because the run property is, itself, a closure. So we create an instance of Effect, and pass it a "run" value that's a closure.)

The "callback in" part, specifically, tells the compiler that, inside that closure, the parameter to the closure should be named "callback".

How to initialise closure variable in swift?

You can initialize closure variable as,

init(onselecteditem : @escaping (Int) -> Void) {
self.onSelectedItem = onselecteditem
}

Assigning closure to struct variable in initialiser

There are two problems:

  • Arguments are passed as selected: ..., not selected = ....
  • There is only a default memberwise initializer which takes all
    properties as arguments.

So this would compile:

var settingsItem = SettingsItem(title: "Title",
textColor: #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1),
selected: { return true },
action: {})

If you define a custom initializer with default argument values

struct SettingsItem {
let title: String
let textColor: UIColor
let selected: () -> Bool
let action: () -> Void

init(title: String,
textColor: UIColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1),
selected: @escaping () -> Bool = { return false },
action: @escaping () -> Void = { })
{
self.title = title
self.textColor = textColor
self.selected = selected
self.action = action
}
}

then the corresponding arguments are optional, for example:

let settingsItem = SettingsItem(title: "Title", selected: { return true })

Initialization of an inferred closure argument

If you can add #[derive(Default)] to your structs, then this works:

// Create an instance of `T` and invoke a closure to initialize its fields.
// Allows creating a `T` without naming it, provided it is used in a context
// that accepts a concrete type. For example:
//
// hello_1(init(Default::default(), |v| v.id = 42));
fn init<T: Default>(mut v: T, f: impl FnOnce(&mut T)) -> T {
f(&mut v);
v
}

macro_rules! call_with_props {
($f: path, $($name: ident, $value: expr),+) => {{
$f(init(Default::default(), |v| {
$(v.$name = $value;)*
}))
}}
}

Playground

Swift initialize a struct with a closure

The closure passed to the constructor modifies the given argument,
therefore it must take an inout-parameter and be called with &self:

public struct Style {

public var test : Int?

public init(_ build:(inout Style) -> Void) {
build(&self)
}
}

var s = Style { (inout value : Style) in
value.test = 1
}

println(s.test) // Optional(1)

Note that using self (as in build(&self)) requires that all its
properties have been initialized. This works here because optionals
are implicitly initialized to nil. Alternatively you could define
the property as a non-optional with an initial value:

public var test : Int = 0


Related Topics



Leave a reply



Submit