I have a struct with 2 variables. This struct has mutating function, but in this function I need to check, which variable to mutate. For this I use separate class' static function with complex logic. This class works with different structs, so for DRY purpose I can't represent this logic in all these structs.
The problem is, that I don't know how to receive the same struct's variable from this separate class, so no struct's variables are mutate. I think, that I miss some Swift knowledge, because I'm sure, that it is possible, without duplicating logic.
Code to represent it in Playground:
struct SomeStruct {
var a = "a"
var b = "b"
mutating func mutateString(to newString: String) {
var varToMutate = VariableDetector.whichVarToMutate(a, b)
varToMutate = newString
// prints to represent question
print("varToMutate: \(varToMutate)")
print("a: \(a)")
print("b: \(b)")
}
}
class VariableDetector {
static func whichVarToMutate(_ first: String, _ second: String) -> String {
var firstOrSecondString = ""
// simple logic to represent question, in real case it is far more complex
if first == "a" {
firstOrSecondString = first
} else {
firstOrSecondString = second
}
return firstOrSecondString
}
}
var someStruct = SomeStruct()
someStruct.mutateString(to: "c")
This code produces:
varToMutate: c
a: a
b: b
Yes, it can be solved with:
if varToMutate == a {
a = newString
} else if varToMutate == b {
b = newString
}
But I want to solve it in more elegant way :)
Thanks for any help!
In Swift 4, this could be done by returning a KeyPath
from whichVarToMutate
. The KeyPath
could then be used to access into the instance in question, and mutate the property it represents.
In Swift 3, there are 2 approaches I can think of:
inout
param, and then has the closure body mutate it.Define a protocol that contains these variables (that you said are shared between multiple types), make those types conform to it, and provide an extension on the protocol that defines a method, which will apply to all of them. This is the approach I would use, even in Swift 4:
struct SomeStruct {
var a = "a"
var b = "b"
}
protocol Mutable { // TODO: Rename me appropriately
var a: String { get set }
var b: String { get set }
}
extension SomeStruct: Mutable {}
extension Mutable {
mutating func changeAppropriateVar(to newValue: String) -> Void {
// simple logic to represent question, in real case it is far more complex
let someCondition = true
if someCondition {
print("Setting `a` to \(newValue)")
a = newValue
}
else {
print("Setting `b` to \(newValue)")
b = newValue
}
}
}
var s = SomeStruct()
s.changeAppropriateVar(to: "foo")