不能对不可变值使用变异成员:函数调用返回不可变值 - 不确定为啥值是不可变的
Posted
技术标签:
【中文标题】不能对不可变值使用变异成员:函数调用返回不可变值 - 不确定为啥值是不可变的【英文标题】:Cannot use mutating member on immutable value: function call returns immutable value - not sure why value is immutable不能对不可变值使用变异成员:函数调用返回不可变值 - 不确定为什么值是不可变的 【发布时间】:2018-01-16 18:38:36 【问题描述】:对于 Swift 开发来说相对较新。试图修改其他人编写的几个函数。目标是在用户登录后第一次调用此路径时(该部分尚未设置)离开原始路径,并在后续调用中使用另一个路径。
所以在编写将指向第一次或非首次通过的逻辑之前,我正在测试非首次通过逻辑。
这里是 allOfferCards():
func allOfferCards() -> [OfferCard]
guard dataSource != nil else
return []
let numberOfCards = self.dataSource!.kolodaNumberOfCards(self)
var offerCards = [OfferCard]()
for i in 0..<numberOfCards
let offerCard = viewForCard(at: i)
if let offerCard = offerCard
offerCards.append(offerCard as! OfferCard)
return offerCards
这就是我尝试进行更改的地方。原始逻辑反转 allOfferCards() 的返回。我想使用一个名为“shuffle”的自定义函数来随机化数组。
func displayOfferCards() -> Void
// What was here originally
//let offerCards = allOfferCards().reversed()
var offerCards = allOfferCards().shuffle()
for (index, offerCard) in offerCards.enumerated()
let delay = Double(index) * 0.2
offerCard.display(delay: delay)
这是随机播放功能
extension Array
/** Randomizes the order of an array's elements. */
mutating func shuffle()
for _ in 0..<10
sort (_,_) in arc4random() < arc4random()
但是,当我尝试运行此程序时,标题中出现错误 - 无法在不可变值上使用变异成员。但是我不确定为什么 allOfferCards() 会生成一个不可变的值 - var offerCards 是使用 var 关键字定义的,而不是 let 关键字 - 这应该意味着它是可变的正确的?
我在这里做错了什么?
【问题讨论】:
这是一个非常非常糟糕的洗牌算法。sort
不会将每个元素都与其他元素进行比较,这样做会非常低效。如果它检查并看到a < b
和c < d
,那么它可以检查b < c
以推断a < b < c < d
而无需检查a < c
、a < d
等等...看看使用适当的Fisher-Yates随机播放:***.com/a/24029847/3141234
@Alexander - 哦,谢谢,我会这样做的。
另外,第一个函数可以简化为两行:gist.github.com/amomchilov/df144a2bee19b627e2163254a42a8a59
我最初没有写它——我们知道有很多逻辑可以重写以提高效率(有些已经有了)。我会看看这个,看看它是否符合我们在这里的计划。
我知道在这样的代码库上工作的感觉,你不想过多地干扰工作状态。幸运的是,这就是我们拥有 VCS 的原因,以保持良好的安全网,防止无意的破坏性更改。但从长远来看,像这样的小增量变化确实会累积并导致实质性改进。我基本上是免费给你的,所以不妨接受它:p
【参考方案1】:
问题是在分配函数的返回值之前,该值本身是不可变的,因此无法直接对其调用变异函数。您应该先将返回值分配给可变变量,然后对其调用变异函数。
func displayOfferCards() -> Void
var offerCards = allOfferCards()
offerCards.shuffle()
for (index, offerCard) in offerCards.enumerated()
let delay = Double(index) * 0.2
offerCard.display(delay: delay)
【讨论】:
这看起来正在运行。我只是要测试一下,我会检查你的答案框。 当我这样做时,我得到元组类型“()”的值没有“枚举”成员。 我在 Playground 中测试了代码(当然注释掉了viewForCard
等未知函数),它编译得很好。您确定您使用的是完全相同的功能吗? offerCards
的类型是 [OfferCard]
,所以使用上面的代码你不会得到那个错误。
我绝对在使用上面列出的功能。会不会是 Swift 3 的东西?
您确定您使用的是完全相同的问题吗?仅仅因为在您的new question 中,您执行了var offerCardsShuffled = offerCards.shuffle()
,这是错误的,绝对不是我在回答中所显示的。【参考方案2】:
补充@Dávid Pásztoranswer。
您可以使用返回随机副本 (shuffled()
) 的变体,而不是使用变异函数 (shuffle()
),类似于 sort()
与 sorted()
。由于没有变量被改变,它都可以在线完成:
func displayOfferCards()
for (index, offerCard) in allOfferCards().shuffled().enumerated()
offerCard.display(delay: Double(index) * 0.2)
有关shuffle()
、shuffled()
的实现,请参阅this answer。
【讨论】:
以上是关于不能对不可变值使用变异成员:函数调用返回不可变值 - 不确定为啥值是不可变的的主要内容,如果未能解决你的问题,请参考以下文章
不能对不可变值使用变异 getter:'self' 是不可变错误
Swift 2在协议扩展中使用变异函数时出错“无法在不可变值上使用变异成员:'self'是不可变的