首页 文章

Swift:通过引用传递数组?

提问于
浏览
108

我想通过引用将我的Swift Array account.chats 传递给 chatsViewController.chats (这样当我向 account.chats 添加聊天时, chatsViewController.chats 仍然指向 account.chats ) . 即,当 account.chats 的长度发生变化时,我不希望Swift将两个数组分开 .

7 回答

  • 21

    Swift中的结构按值传递,但您可以使用 inout 修饰符修改数组(请参阅下面的答案) . 类通过引用传递 . Swift中的 ArrayDictionary 作为结构实现 .

  • 126

    对于函数参数运算符,我们使用

    let (它是默认运算符,所以我们可以省略 let )使参数保持不变(这意味着我们甚至无法修改本地副本);

    var 使其变量(我们可以在本地修改它,但它不会影响已传递给函数的外部变量);和

    inout 使其成为输入输出参数 . In-out实际上意味着通过引用而不是通过值传递变量 . 并且它不仅要求通过引用接受值,还要通过引用传递它,所以传递它与 & - foo(&myVar) 而不仅仅是 foo(myVar)

    所以这样做:

    var arr = [1, 2, 3]
    
    func addItem(inout localArr: [Int]) {
        localArr.append(4)
    }
    
    addItem(&arr)    
    println(arr) // it will print [1, 2, 3, 4]
    

    确切地说,它不仅仅是一个引用,而是外部变量的真正别名,因此您可以使用任何变量类型执行此类技巧,例如使用整数(您可以为其指定新值),尽管它可能不是良好的做法,修改像这样的原始数据类型可能会令人困惑 .

  • 2

    定义一个实现 Array 接口的 BoxedArray<T> ,但将所有函数委托给存储的属性 . 因此

    class BoxedArray<T> : MutableCollection, Reflectable, ... {
      var array : Array<T>
    
      // ...
    
      subscript (index: Int) -> T { 
        get { return array[index] }
        set(newValue) { array[index] = newValue }
      }
    }
    

    在您使用 Array 的任何地方使用 BoxedArray . 分配 BoxedArray 将通过引用,它是一个类,因此通过 Array 接口对存储属性的更改将对所有引用可见 .

  • 15

    对于Swift版本3-4(XCode 8-9),请使用

    var arr = [1, 2, 3]
    
    func addItem(_ localArr: inout [Int]) {
        localArr.append(4)
    }
    
    addItem(&arr)
    print(arr)
    
  • 60

    就像是

    var a : Int[] = []
    func test(inout b : Int[]) {
        b += [1,2,3,4,5]
    }
    test(&a)
    println(a)
    

    ???

  • 0

    另一个选择是让阵列的消费者根据需要向所有者询问 . 例如,有些东西:

    class Account {
        var chats : [String]!
        var chatsViewController : ChatsViewController!
    
        func InitViewController() {
            chatsViewController.getChats = { return self.chats }
        }
    
    }
    
    class ChatsViewController {
        var getChats: (() -> ([String]))!
    
        func doSomethingWithChats() {
            let chats = getChats()
            // use it as needed
        }
    }
    

    然后,您可以在Account类中根据需要修改数组 . 请注意,如果您还想从视图控制器类修改数组,这对您没有帮助 .

  • 3

    使用 inout 是一种解决方案,但由于数组是值类型,因此对我来说感觉不太开心 . 在风格上我个人更喜欢返回变异副本:

    func doSomething(to arr: [Int]) -> [Int] {
        var arr = arr
        arr.append(3) // or likely some more complex operation
        return arr
    }
    
    var ids = [1, 2]
    ids = doSomething(to: ids)
    print(ids) // [1,2,3]
    

相关问题