I'm trying to write a function that takes a variable pointer and a descriptor/key and sets a new value for the variable. Ideally the pointer should be either of an object or a primitive, but I could also live with separate functions (or an additional parameter). In my code I retrieve the new value from a database also using the key, but in the following example I simplified it with dummy values so that it can be used easily in a playground:
import UIKit
func setValue(inout object: AnyObject, key: String) {
switch key {
case "String":
object = "A String"
case "UIColor":
object = UIColor.whiteColor()
case "Bool":
object = true
default:
println("Unhandled key: \(key)")
}
}
var string: String = "Default String"
var color: UIColor = UIColor.blackColor()
var bool: Bool = false
setValue(&string, "String")
setValue(&color, "UIColor")
setValue(&bool, "Bool")
I get the following error:
"Cannot invoke 'setValue' with an argument list of type '(inout String, key String)'"
I understand that I'm mixing Objects and Primitives here. I also tried to break it down and separate these into two functions, but even that fails:
func setValue(inout object: AnyObject, key: String) {
switch key {
case "UIColor":
object = UIColor.whiteColor()
default:
println("Unhandled key: \(key)")
}
}
var color: UIColor = UIColor.blackColor()
setValue(&color, "UIColor")
This also gives the same error:
"Cannot invoke 'setValue' with an argument list of type '(inout UIColor, key String)'"
If I change 'AnyObject' to 'UIColor' it works, but the point of the function is, that it takes any variable type or at least any object type (I'd write a second function using "Any" for primitives then or add another parameter)
In Objective-C I was using pointers, transferring the approach to Swift also doesn't work, same result:
func setValue(object: UnsafeMutablePointer<AnyObject>, key: String) {
switch key {
case "String":
object.memory = "A String"
case "UIColor":
object.memory = UIColor.whiteColor()
case "Bool":
object.memory = true
default:
println("Unhandled key: \(key)")
}
}
Does anybody have an idea what I'm missing here? Any help is much appreciated!
Thanks!
A good use case will be swap function that it will modify the passed-in parameters. Swift 3+ Note: Starting in Swift 3, the inout keyword must come after the colon and before the type. For example, Swift 3+ now requires func changeChar(char: inout Character) .
Swift inout parameter is a parameter that can be changed inside the function where it's passed into. To accept inout parameters, use the inout keyword in front of an argument. To pass a variable as an inout parameter, use the & operator in front of the parameter.
If you want, you can pass in one or more parameters as inout , which means they can be changed inside your function, and those changes reflect in the original value outside the function.
You write an in-out parameter by placing the inout keyword right before a parameter's type. An in-out parameter has a value that's passed in to the function, is modified by the function, and is passed back out of the function to replace the original value.
Better you can create a generic method like below:
func setValue<T>(inout object:T, key: String) {
switch key {
case "String":
object = ("A String" as? T)!
case "UIColor":
object = (UIColor.whiteColor() as? T)!
case "Bool":
object = (true as? T)!
default:
println("Unhandled key: \(key)")
}
}
And calling will be like this:
setValue(&string, key: "String")
setValue(&color, key: "UIColor")
setValue(&bool, key: "Bool")
Hope it helps!
The right way to do this is to use overloading, and letting the compiler choose the appropriate bit of code at compile time, instead of switching off a string at runtime:
func setValue(inout object: String) {
object = "A String"
}
func setValue(inout object: UIColor) {
object = UIColor.whiteColor()
}
func setValue(inout object: Bool) {
object = true
}
func setValue(inout object: Any) {
println("Unhandled key: \(key)")
}
This approach wouldn’t work when you have an Any
and you want to indicate to the function what type is contained in the Any
… but in this case, the reason you have problems is that the compiler does know what the types are, so you can take advantage of that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With