swift中的可选链接和数组

Mat*_*oal 1 swift

让我们用这两个简单的类来表明我的问题:

class Object{  
    var name:String?
    // keep it simple... and useless
}

class TestClass {
    var objects:AnyObject[]? 

    func initializeObjects (){
        objects?.insert(Object(), atIndex:0) // Error
        objects?.insert(Object(), atIndex:1) // Error
        objects?.insert(Object(), atIndex:2) // Error
    }
}
Run Code Online (Sandbox Code Playgroud)

通过这个实现,我得到3个错误Could not find member 'insert',我尝试将对象添加到objects数组中.

现在,如果我从objects定义中删除可选项并且其中的可选链条initializeObjects没有问题(这里是工作代码)

class Object{
    var name:String?
}

class TestClass {
    var objects:AnyObject[] = AnyObject[]() // REMOVE optional and initialize an empty array

    func initializeObjects (){
        objects.insert(Object(), atIndex:0) // Remove Opt chaining 
        objects.insert(Object(), atIndex:1) // Remove Opt chaining
        objects.insert(Object(), atIndex:2) // Remove Opt chaining
    }
}
Run Code Online (Sandbox Code Playgroud)

我无法理解第一次实施中出了什么问题.我认为它检查objects?是否objects不是nil,此时它添加了一个元素使用insert:atIndex:.但我可能错了 - .-

Sul*_*han 5

Swift中的数组是结构体,结构体是值类型.
Swift中的Optionals实际上是枚举(Optional<T>ImplicitlyUnwrappedOptional<T>).

当您展开值类型的可选(隐式或显式)时,您获得的实际上是结构的常量副本.而且你不能mutating在常量结构上调用方法.

执行objects?.insert(Object(), atIndex:0)基本上意味着:

if let tmp = objects {
    tmp.insert(Object(), atIndex:0)
}
Run Code Online (Sandbox Code Playgroud)

作为解决方法,您需要将展开的值分配给变量,然后将变量分配回可选属性.这就是价值类型的工作方式.

这对任何结构都是可重现的,不仅仅是数组:

struct S {
    var value: Int = 0
}

var varS: S = S()
varS.value = 10 //can be called

let constS: S = S()
constS.value = 10 //cannot be called - constant!

var optionalS: S? = S()
optionalS?.value = 10 //cannot be called, unwrapping makes a constant copy!

//workaround
if optionalS {
    var tmpS = optionalS!
    tmpS.value = 10
    optionalS = tmpS
}
Run Code Online (Sandbox Code Playgroud)

这里有一些相关的讨论:https://devforums.apple.com/thread/233111?tstart = 60