Swift可选inout参数和nil

时间:2014-07-11 05:37:14

标签: swift optional

是否可以在Swift中为函数设置Optional inout参数?我想这样做:

func testFunc( inout optionalParam: MyClass? ) {
    if optionalParam {
        ...
    }
}

...但是当我尝试调用它并通过nil时,它给了我一个奇怪的编译错误:

Type 'inout MyClass?' does not conform to protocol 'NilLiteralConvertible'

我不明白为什么我的类在已经被声明为可选的时候必须符合某些特殊协议。

5 个答案:

答案 0 :(得分:26)

它不会编译,因为函数需要引用但是你通过了nil。这个问题与可选问题无关。

通过使用inout声明参数意味着您将在函数体内为其指定一些值。如何为nil分配价值?

您需要将其称为

var a : MyClass? = nil
testFunc(&a) // value of a can be changed inside the function

如果您了解C ++,那么这是您的代码的C ++版本,没有可选的

struct MyClass {};    
void testFunc(MyClass &p) {}
int main () { testFunc(nullptr); }

您有此错误消息

main.cpp:6:6: note: candidate function not viable: no known conversion from 'nullptr_t' to 'MyClass &' for 1st argument

这相当于你得到的(但更容易理解)

答案 1 :(得分:3)

这是可能的,它可能与Closure。()

有关

可选的可以有一个nil值,但它不会期望为零。因此,如果你只是没有将它传递给函数或者传递MyClass类型的变量,那么可选的是可行的吗?价值为零。像布莱恩一样。

编写函数时,必须将默认值作为可选参数,如下所示:

func testFunc(inout optionalParam:MyClass?={var nilRef:MyClass?;return &nilRef}()) {
    if optionalParam != nil {
        ...
    }
}

注意if optionalParam {...}已更改为if optionalParam != nil {...}

你不能不检查它optionalParam,即if optionalParam? != nil,因为在optionalParam?时,optionalParam==nil失败,var a :MyClass?失败。 〜注意,testFunc(optionalParam:&a)的值为nil,直到分配为止。

来电是testFunc()testFunc(nil),但绝不是{{1}}

认为你可能会得到两个相互交织的概念,因为它们有相似的名称,可选参数和选项。 Optionals是具有扩展nil条件的变量。可选参数是可选的功能参数。

进一步阅读here。 Apple正试图将可选参数的措辞改为“带默认值的参数”。不幸的是,他们没有在这些新的可选内容中包含可选参数行为。如果在打开时它们会失败,那么将nil选项作为选项传递的重点是什么?如果它可以在打开之前通过,它可能会更深入地了解这个可选项的核心...... Schrodinger的猫

答案 2 :(得分:2)

确切的passage from the docs是:

  

您只能将变量作为输入输出参数的参数传递。   您不能传递常量或文字值作为参数,因为   常量和文字不能修改。你放了一个&符号(&)   当您将变量作为参数传递给变量时,直接在变量名称之前   一个inout参数,表示它可以被修改   功能

但请注意,根据@ gnasher的评论(编辑),您只需要将一个类作为inout(也就是通过引用)传递,如果您打算或希望允许实例被/替换为另一个实例,而不仅仅是原始修改。文档中涉及此内容的段落是:

  

输入输出参数

     

如上所述,变量参数只能在其中更改   功能本身。如果你想要一个函数来修改参数   值,并且您希望在函数调用后这些更改仍然存在   已结束,请将该参数定义为输入输出参数。

以下是三个测试,涵盖了var和inout的用法。

class Bar : Printable {
    var value = 1

    init(_ value:Int) { self.value = value }
    var description:String { return "Bar is: \(value)" }
}

let bar = Bar(1)
func changeBarWithoutInoutSinceBarIsAClassYaySwift(b:Bar) { b.value = 2 }
changeBarWithoutInoutSinceBarIsAClassYaySwift(bar)
println("after: \(bar)") // 2

var bar2 = Bar(0)
func tryToReplaceLocalBarWithoutInout(var b:Bar) { b = Bar(99) }
tryToReplaceLocalBarWithoutInout(bar2)
println("after: \(bar2)") // 0

var bar3 = Bar(0)
func replaceClassInstanceViaInout(inout b:Bar) { b = Bar(99) }
replaceClassInstanceViaInout(&bar3)
println("after: \(bar3)") // 99

答案 3 :(得分:1)

实际上@ devios1需要的是"可选指针"。 但是在MyClass中呢?表示"指向可选"的指针。 以下内容适用于Swift 4

class MyClass {
    // func foo() {}
}

func testFunc(_ optionalParam: UnsafeMutablePointer<MyClass>? ) {
    if let optionalParam = optionalParam {
        // optionalParam.pointee.foo()
        // optionalParam.pointee = MyClass()
    }
}

testFunc(nil)

var myClass = MyClass()
testFunc(&myClass)

答案 4 :(得分:-3)

这是可能的,但你必须更换&#39; inout&#39;与&#39; var&#39;

这仅适用于Class参数,不适用于Struct。一个类对象作为指针传递,&#34; inout&#34;不需要修饰符(实际上是错误)。 &#39; var&#39;必须添加属性,因为您要在函数内更改其值。