Home > Enterprise >  Is it possible to point class instance variables to `inout` parameters in Swift?
Is it possible to point class instance variables to `inout` parameters in Swift?

Time:01-04

Is it possible for multiple class methods to access and modify a single inout parameter that is set in the class constructor? For example something like this:

class X {
    var mySwitch: Bool
    
    init(mySwitch: inout Bool) {
        self.mySwitch = mySwitch
    }
    
    func updateSwitch() {
        self.mySwitch.toggle() // this should toggle the external Boolean value that was originally passed into the init
  }
}

// usage
var myBool: Bool = false
let x = X(mySwitch: &myBool)
x.updateSwitch()
print(myBool) // this should read 'true'

CodePudding user response:

Short Answer

No.

Long Answer

There are other approaches that can satisfy this.

Binding Variables

In SwiftUI we use Binding Variables to do stuff like this. When the Binding variable updates, it also updates the bound variable. I'm not sure if it will work in Sprite Kit.

class X {
    var mySwitch: Binding<Bool>

    init(_ someSwitch: Binding<Bool>) {
        self.mySwitch = someSwitch 
    }

   func toggle() { mySwitch.wrappedValue.toggle() }
}

struct Y {
    @State var mySwitch: Bool = false
    lazy var switchHandler = X($mySwitch)
} 

Callbacks

We can add a callback to X and call it on didSet of the boolean.

class X {
    var mySwitch: Bool {
        didSet { self.callback(mySwitch) } // hands the new value back to the call site in Y
    }

    let callback: (Bool) -> Void

    init(_ someSwitch: Bool, _ callback: @escaping (Bool) -> Void) {
        self.mySwitch = someSwitch
        self.callback = callback
    }

    func toggle() { mySwitch = !mySwitch } // explicitly set to trigger didSet
}

class Y {
    var mySwitch: Bool = false
    lazy var switchHandler = X(mySwitch) {
        self.mySwitch = $0 // this is where we update the local value
    }
}

CodePudding user response:

You can't "link" a variable that way because inout only works in the scope it's declared.

If what you want is to have some kind of global state, you can wrap it in a class.

class Wrapper {
    var value = false
    init() {}
}

class Modifier {
    let wrapper: Wrapper
    init(wrapper: Wrapper) {
        self.wrapper = wrapper
    }
    
    func updateSwitch() {
        wrapper.value.toggle()
    }
}

let wrapper = Wrapper()
let modifier = Modifier(wrapper: wrapper)
modifier.updateSwitch()
print(wrapper.value) // this will read 'true'

CodePudding user response:

Short answer: NO.

Your question does not make sense. An inout parameter allows you read/write access to the parameter during the call to function. It has no meaning once the function returns. You sem to think it creates some persistent link between the parameter that is passed as inout and some other variable. It DOES NOT.

  •  Tags:  
  • Related