Swift / iOS:如何在AnyObject / Any或Pointers的函数中使用inout参数

我试图编写一个函数,它需要一个variables指针和一个描述符/键,并为variables设置一个新的值。 理想情况下,指针应该是一个对象或一个原语,但我也可以使用单独的函数(或附加参数)。 在我的代码中,我也使用键从数据库中检索新值,但在下面的示例中,我使用虚拟值对其进行了简化,以便在操场中轻松使用它:

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") 

我得到以下错误:

“不能用types为'(inout String,key String)'的参数列表来调用'setValue''”

我明白,我在这里混合对象和原始。 我也试图把它分解成两个function,但即使这样做也失败了:

 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") 

这也给出了同样的错误:

“不能用types'(inout UIColor,key String)'的参数列表调用'setValue''”

如果我将“AnyObject”更改为“UIColor”,它可以工作,但函数的要点是,它需要任何variablestypes或至less任何对象types(我会写入第二个函数使用“任何”另一个参数)

在Objective-C中,我使用的是指针,将方法传递给Swift也不起作用,结果相同:

 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)") } } 

有没有人知道我在这里错过了什么? 任何帮助深表感谢!

谢谢!

最好你可以创build一个像下面这样的通用方法:

 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)") } } 

而且打电话会是这样的:

 setValue(&string, key: "String") setValue(&color, key: "UIColor") setValue(&bool, key: "Bool") 

希望能帮助到你!

正确的做法是使用重载,并让编译器在编译时select合适的代码位,而不是在运行时closuresstring:

 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)") } 

当你有一个Any时,这个方法是行不通的,而你想要告诉函数什么types包含在Any ,但在这种情况下,你遇到问题的原因是编译器确实知道types是什么,所以你可以利用这一点。

– 使用Any而不是AnyObject来覆盖值types和结构。

– 在调用你的方法之前,你可能需要投射任何东西。

例:

 func swapAny( inout obj1: Any, inout obj2: Any ) { let temp = obj1 obj1 = obj2 obj2 = temp } 

使用:

 var fooString: Any = "Foo" var barString: Any = "Bar" swapAny(&fooString, obj2: &barString) println(fooString)//prints "Bar" 

协议支持inout

当你将一个类转换成一个协议时,你最终得到一个不可变的引用,这个引用不能用在inout函数参数中。 所以你可以:

  1. 使用方法重载(它可以复制你的代码,并使其更加难以阅读,即使你重构)
  2. 不用inout(这是你应该做的)
  3. 或者你可以这样做:

 protocol IPositional{ func setPosition(position:CGPoint) } extension IPositional{ var positional:IPositional {get{return self as IPositional}set{}} } class A:IPositional{ var position:CGPoint = CGPoint() func setPosition(position:CGPoint){ self.position = position } } func test(inout positional:IPositional){ positional.setPosition(CGPointMake(10,10)) } var a = A() test(&a.positional) a.position//output: (10.0, 10.0) 

结论:
这样做的好处是:你现在可以为所有实现IPositional的类使用一个“inout方法”,但是我build议使用选项2(不使用inout)

对象的types应该与参数的types相匹配,包括AnyObject

 func setValue(inout object: AnyObject, key: String) { switch key { case "String": object = "A String" case "UIColor": object = UIColor.whiteColor() case "Bool": object = true default: print("Unhandled key: \(key)") } } var string: AnyObject = "Default String" var color: AnyObject = UIColor.blackColor() var bool: AnyObject = false setValue(&string, key: "String") setValue(&color, key: "UIColor") setValue(&bool, key: "Bool")