【问题标题】:Pass a variable reference to a instance property将变量引用传递给实例属性
【发布时间】:2020-09-25 09:49:20
【问题描述】:

我想确保如果更新原始变量,实例属性也会更新。

class Sample {

    var number: Int
    
    init(number: inout Int) {
        self.number = number
    }
}

var number = 0
let sample = Sample(number: &number)

number = 1
print(sample.number)    // 0

在上面的代码中,实例属性没有更新。
我该如何解决?

【问题讨论】:

  • 一个inout函数参数有一个值被传入函数,被函数修改,并被传回函数外以替换原始值。它不会为传递给函数的变量创建某种永久绑定。 Int 是一个值类型。您可以尝试使用 NSNumber 代替,它是一个类,因此是一个引用类型。
  • Swift中的值类型和引用类型stackoverflow.com/questions/44195908/…
  • 如何在 Swift 中获取值类型的引用? stackoverflow.com/questions/42138449/…

标签: swift pass-by-reference


【解决方案1】:

inout 参数是这样工作的(source):

  1. 调用函数时,会复制参数的值。
  2. 在函数体中,修改了副本。
  3. 当函数返回时,副本的值被分配给原始参数。

这不是 C 或 C++ 意义上的“通过引用传递”。您没有将“引用”传递给初始化程序。编译器可以优化inout参数,使原始和副本使用相同的内存地址,但在这一点上,你知道的太多了:)

因此,您尝试做的事情并没有真正的意义。您似乎希望Sample.number 存储对您传入的Int 的“引用”,但这是不可能的,因为Int 是一个值类型。

您必须为Int 创建自己的包装类:

class IntWrapper : ExpressibleByIntegerLiteral, CustomStringConvertible {
    var wrapped: Int
    
    required init(integerLiteral value: Int) {
        wrapped = value
    }
    
    var description: String { wrapped.description }
}

class Sample {

    let number: IntWrapper
    
    init(number: IntWrapper) {
        self.number = number
    }
}

let number: IntWrapper = 0
let sample = Sample(number: number)

number.wrapped = 1
print(sample.number)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-25
    • 2021-08-20
    • 2014-09-15
    • 2018-09-29
    • 1970-01-01
    相关资源
    最近更新 更多