由于两个存储属性不’;在Swift中不能以任何方式进行交互?
我试图理解Swift中的记忆安全,我对两种情况感到困惑 正如我标记的MARK1:-在方法中对self的访问冲突部分是有意义的。两个写访问使彼此重叠。编译器在运行前已给我错误: 重复访问“robGlobal”,但修改需要独占访问;考虑复制到局部变量由于两个存储属性不’;在Swift中不能以任何方式进行交互?,swift,Swift,我试图理解Swift中的记忆安全,我对两种情况感到困惑 正如我标记的MARK1:-在方法中对self的访问冲突部分是有意义的。两个写访问使彼此重叠。编译器在运行前已给我错误: 重复访问“robGlobal”,但修改需要独占访问;考虑复制到局部变量 问题一:好的,但是关于标记2部分呢?Swift编译器进行了一些优化,以解决struct的写入访问问题 苹果公司解释解决方案如下,但我不清楚 编译器可以证明内存安全性得到了保护,因为这两个存储的属性不会以任何方式交互 问题二:通过在此处创建全局运行时,
问题一:好的,但是关于标记2部分呢?Swift编译器进行了一些优化,以解决struct的写入访问问题 苹果公司解释解决方案如下,但我不清楚 编译器可以证明内存安全性得到了保护,因为这两个存储的属性不会以任何方式交互 问题二:通过在此处创建全局运行时,问题得以解决。但我想知道怎么做?还有为什么它不适用于MARK1部分,为什么
PS:使用
robGlobal.someFunction()
,您正在对robLocal
的单独本地实例调用shareHealth
。显然,在这种情况下没有内存安全问题
但是使用robGlobal.anotherFunction()
,您随后调用了robGlobal
的一个实例方法,但随后将对同一robGlobal
的另一个引用传递到shareHealth
,因此内存安全冲突
但这很好。这在功能上等同于内存安全检查保护您免受的其他尝试之一:
import UIKit
var robGlobal = Player(name: "Rob", health: 10, energy: 10)
var matt = Player(name: "Matt", health: 5, energy: 10)
struct Player {
var name: String
var health: Int
var energy: Int
static let maxHealth = 10
mutating func restoreHealth() {
health = Player.maxHealth
}
func balance(_ x: inout Int, _ y: inout Int) {
let sum = x + y
x = sum / 2
y = sum - x
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//MARK1: -Conflicting Access to self in Methods
robGlobal.shareHealth(with: &matt)
robGlobal.shareHealth(with: &robGlobal) // NOT OK in compile time Error: //Overlapping accesses to 'robGlobal', but modification requires exclusive access; consider copying to a local variable
var robNewLocal = Player(name: "Rob", health: 10, energy: 10)
robNewLocal.shareHealth(with: &robNewLocal) // NOT OK in compile time
//MARK2: -Conflicting Access to properties in Methods
robGlobal.someFunction() // OK
robGlobal.anotherFunction() // NOT OK in Run Time Error: Thread 1: Simultaneous accesses to 0x108cc4050, but modification requires exclusive access
}
}
extension Player {
mutating func shareHealth(with teammate: inout Player) {
balance(&teammate.health, &health)
}
func someFunction() {
var robLocal = Player(name: "Rob", health: 10, energy: 10)
balance(&robLocal.health, &robLocal.energy) // OK
}
func anotherFunction() {
balance(&robGlobal.health, &robGlobal.energy) // NOT OK in Run Time
}
}
整个想法是与其他玩家共享健康。撇开记忆安全检查不谈,与自己分享一名玩家的健康状况意味着什么?你目前的健康状况是11岁。然后你自己“分享”它。那么,你现在的健康状况如何?还是6号?你的健康状况是11岁,而现在在你与自己分享之后,它的价值变小了,这有意义吗?与自己分享的想法毫无意义。“内存安全”检查可以保护您免受此类误用
就我个人而言,我会的
- 使
成为balance
方法,因为它所做的一切都是“平衡”两个整数值,而不是对当前实例做任何事情static
- 这也可能是私有的,因为不需要公开这个函数;及
- 既然你似乎想“分享健康”来平衡两个玩家之间的健康,以及平衡一个给定玩家的健康和能量,我会写这两种方法
struct播放器{
变量名称:String
变量健康:Int
无功能量:Int
静态let maxHealth=10
}
//标记:-接口
分机{
变异功能恢复健康(){
health=Player.maxHealth
}
变异func shareHealth(队友:inout玩家){
自我平衡(和队友健康和健康)
}
突变功能平衡健康与能量(){
自我平衡(健康和精力)
}
}
//MARK:-专用实用程序方法
专用扩展播放器{
静态函数平衡(x:inout Int,y:inout Int){
设和=x+y
x=总和/2
y=和-x
}
}
然后,您可以执行以下操作:
func someFunction(){
var rob=玩家(名字:“rob”,生命值:20,能量值:10)
rob.balanceHealthAndEnergy()
}
func另一个函数(){
var rob=玩家(名字:“rob”,生命值:10,能量值:10)
var matt=玩家(名字:“matt”,生命值:5,能量值:10)
rob.shareHealth(带:&matt)
}
这个新的界面(共享健康和平衡健康与能源)简化了界面。您可以在本地变量或属性(或者全局变量,如果您真的愿意的话;但是使用全局变量通常是个坏主意)上调用它们。但是你永远不会与自己分享健康,既然平衡是私人的,它就可以最大限度地减少你问题中提到的误用
FWIW,我不会让这些测试方法成为
Player
的实例方法,因为它们没有对当前实例做任何事情。你可以让它们成为静态的方法。或者,您可以在您的模型(或测试或其他)中创建这些方法。但是它们作为Player
实例方法没有意义。请不要结束这个问题。如果你觉得不清楚,我可以再详细解释一下。我不清楚问题是什么,因为错误看起来很清楚。您正在对对象调用一个mutating方法,同时还将结构作为参数传递。那么问题是什么呢?@Rob我真的很想知道func someFunction()怎么行。。我正在传递相同的对象(相同的内存位置),但编译不抱怨并且正在工作。。那么引擎盖下发生了什么。。我读了你的相关答案,但无法理解这个例子使本地实例(放在函数中)有多不同?请检查anotherFunction()(使用全局实例)是否正常工作,因此我很困惑“您正在对对象调用一个变异方法,同时还将结构作为参数传递”——someFunction没有执行相同的操作?Swift Memory Access文档中的属性访问冲突部分解释了我的问题,但无法理解,也许您可以更清楚地解释。谢谢你,你的回答很好。在你说“环球旅行通常是个坏主意”之后,我现在问自己。我想你需要问一个新问题this@DrainOpener-我会在谷歌上搜索“全球都是邪恶的”,你会看到大量点击。这个话题已经在这里和互联网上的其他地方讨论过了,如果你不研究它,你的问题就不会受到欢迎(坦率地说,常规搜索无疑会消除n
robGlobal.shareHealth(with: &robGlobal)