隐式解包可选使不可变

dre*_*wag 10 swift

为什么我不能改变一个隐式解包的可选变量?

以下是重现问题的简短示例:

使用Array

var list: [Int]! = [1]
list.append(10) // Error here
Run Code Online (Sandbox Code Playgroud)

Immutable value of type '[Int]' only has mutating members named 'append'

用Int

var number: Int! = 1
number = 2
number = 2 + number
number += 2 // Error here
Run Code Online (Sandbox Code Playgroud)

Could not find an overload for '+=' that accepts the supplied arguments

Ana*_*ile 5

因为你试图改变它们的方式是通过改变值(它们是不可变的)而不是改变它var.

在Swift中,值类型是不可变的.一直都是.

变异不是值的变异,它是包含值的变量的变异.

在这种情况下Int,+=运算符在左侧获得一个结构,在右侧获得一个Int,并且它不能向int添加结构.

在的情况下Arrayappend是一个突变体.但是它是在一个不直接存储在变量中的不可变值上调用的.它只能对直接存储在变量中的值进行操作(这使得它们变得可变:它们存储在变量中的事实.它们实际上不是可变的,变量是).

  • 它是可变的变量,而不是值.值类型的值始终是不可变的.文档有时以非正式方式说话,有时则更正式.当它表示字符串或数组在分配给`var`时是可变的,并且在分配给`let`时是不可变的,它只是说值本身是不可变的,但你可以将它赋给一个可变的`var`和mutate变种 这就是为什么你不能调用任何只是另一种类型的构造函数的参数的变异方法. (4认同)
  • 目前尚不清楚.它并不意味着你认为它意味着什么.这意味着您可以调用该值的变异方法.变异方法的作用是采用隐藏的参数,即变量的地址,创建一个新值,并将其赋值给变量.它们不会改变实际的原始值(除非编译器能够证明没有别名或共享,在这种情况下它可以执行优化并实际改变原始存储,但这会透明地发生). (3认同)

dre*_*wag 4

更新:

这个问题已在 Xcode Beta 5 中得到修复,但有一个小警告:

var list: [Int]! = [1]
list.append(10)

var number: Int! = 1
number! += 2
number += 2 // compile error
Run Code Online (Sandbox Code Playgroud)

该数组按预期工作,但现在看来整数仍然需要显式解包才能允许使用+=


目前,这只是可选的本质(无论是否隐式解包)。展开运算符返回一个不可变的值。这很可能会得到修复,或者将来会提供更好的解决方案

目前唯一的解决方法是将数组包装在一个类中:

class IntArray {
    var elements : [Int]
}
Run Code Online (Sandbox Code Playgroud)