提问人:meaning-matters 提问时间:9/5/2016 最后编辑:meaning-matters 更新时间:9/1/2022 访问量:18729
forEach 导致 $0 是不可变错误
forEach results in $0 is immutable error
问:
protocols.forEach { $0.prop = nil }
结果如下:
Cannot assign to property: '$0' is immutable
我解决了这个问题:
protocols.forEach
{
var protocol = $0
protocol.prop = nil
}
但是为什么编译器可以接受呢?我希望它能解决这个问题。
答:
58赞
vacawama
9/5/2016
#1
您有一组实现协议的项。如果你不告诉 Swift 这是一个协议(或早期版本的 Swift 中的协议),它将假定它可以由 .AnyObject
class
struct
在循环中,您基本上将依次将一个变量(默认调用)分配给数组中的每个值。如果有一个对象数组(实例 ),则可以修改该项的属性。如果你有一个项目数组,那么这些项目将是不可变的。如果你有一个实现协议的项数组,那么 Swift 会将它们视为限制性更强的项,除非你添加(或在早期版本的 Swift 中)到你的协议定义中。forEach
let
$0
class
struct
struct
: AnyObject
: class
例如:
protocol Xyzzy: AnyObject {
var prop: Int? { get set }
}
class Fred: Xyzzy, CustomStringConvertible {
var description: String { String(describing: prop) }
var prop: Int? = 17
}
let objects: [Xyzzy] = [Fred(), Fred(), Fred()]
print(objects) // [Optional(17), Optional(17), Optional(17)]
objects.forEach { $0.prop = nil }
print(objects) // [nil, nil, nil]
解决方法:
protocols.forEach
{
var protocol = $0
protocol.prop = nil
}
适用于对象,因为它创建指向对象的新指针,然后允许您修改对象。请注意,此解决方法仅适用于类的实例。如果您的协议是由 实现的,则 new 将是该项的新副本,并且数组中的原始副本不会更改。class
var
struct
var
struct
评论
2赞
meaning-matters
9/5/2016
很好的答案,有助于更深入地了解 Swift。谢谢!
0赞
0xxxD
5/14/2019
那么为什么会这样呢?还有更深层次的原因吗? 像内存布局/编译器改进/结构体这样的东西是 swift 中的值类型?
2赞
vacawama
5/14/2019
@0xxxD,在 Swift 中,所有类型在编译时都是已知的。结构体和类可以采用的协议被视为限制性更强的结构体,因为 Swift 不会在运行时做出动态决策。是的,结构是值类型。当它们被分配给 let 常量(如循环变量)时,所有属性都是不可变的。声明一个协议告诉 Swift,你只会将它与类一起使用,而 Swift 在编译时会将该协议类型的变量视为引用。class
0赞
adamjansch
9/1/2022
截至 2021 年 (?),该协议需要而不是 ,因为后者已被弃用。AnyObject
class
1赞
vacawama
9/1/2022
@adamjansch,感谢您帮助我更新此答案!
27赞
Denis Rybkin
2/17/2021
#2
如何更改Array
Structs
对于每个元素:
itemsArray.indices.forEach { itemsArray[$0].someValue = newValue }
对于特定元素:
itemsArray.indices.filter { itemsArray[$0].propertyToCompare == true }
.forEach { itemsArray[$0].someValue = newValue }
评论
2赞
mushcraft
9/15/2021
我几乎用过这个,但我不得不评论未来的自己或其他人发生了什么。感觉也没有那么快。所以发现有作为序列协议的一部分。我用了它。 Map 现在将有两个默认参数:$0 是索引,$1 是值。或enumerated
itemsArray.enumerated().map
itemsArray.enumerated().map{ index, value in //morecode }
0赞
steveSarsawa
2/10/2023
脱帽致敬,你节省了我的时间:)
评论
protocol
": class"
: class
var
class