【问题标题】:How to pass array by reference without function ? swift如何在没有函数的情况下通过引用传递数组?迅速
【发布时间】:2016-05-25 07:15:17
【问题描述】:

我有这门课:

class MainView:UIView{

    var categories:[Category]!

}

我想设置类别 arg,但我需要通过引用而不是值来传递它。因为它更高效、更好。

如果我这样做了:

let mainView  = MainView()
mainView.categories = categoriesData.

然后它按值传递它。

如果我需要通过引用传递它,我可以通过使用 MainView() 中的函数来做到这一点

class MainView:UIView{

    var categories:[Category]!
    fun setCategories(inout categories: Int){
            self.categories = categories;

    }

}

但如果我不想使用 set 函数,我怎么能通过引用传递它。 例如

mainView.categories = &categoriesData. 但这不起作用?谢谢

【问题讨论】:

  • @matt 感谢您的回复。我不明白你的意思。我需要通过引用传递类别,因为我不想复制,因为这是多余的。我错了吗?
  • @matt 这一行 "mainView.categories = categoriesData" 它不会将数组复制到另一个数组?
  • @matt 怎么没有?请看这个:stackoverflow.com/questions/28889705/…,它表明数组是按值传递的
  • @matt 为什么你删除了你的 cmets ?
  • 是什么让您认为通过引用传递更快更好?您需要阅读一些有关 Swift 的信息。编译器是聪明的。只有当数组或原始数组被修改时,数组才会被复制,在这种情况下,您真的不想要引用,而是想要一个副本。

标签: ios swift ios8 ios9 pass-by-reference


【解决方案1】:

Swift 在处理数组时使用 ARC(自动引用计数),它会延迟复制数组,直到其中一个副本被修改:

例如:

var a = [1, 2, 3, 4, 5]
let b = a
let c = a   // 1

a.append(6) // 2

print(a.count)
print(b.count)
print(c.count)

在上面的步骤 1 中,内存中只有一个 [1, 2, 3, 4, 5] 的副本,abc 是对它的引用。

a在步骤2中被修改时,Swift给出a和数组的新副本,bc继续引用原始数组。所以现在内存中有2个数组副本。


让我们看一个更复杂的例子:

class Person: CustomStringConvertible {
    let name: String
    var friends: [Person] = []

    init(name: String) {
        self.name = name
    }

    var description: String { return name }
}

func createFredsFriends() -> [Person] {
    let barney = Person(name: "Barney")
    let wilma = Person(name: "Wilma")
    let betty = Person(name: "Betty")
    let friends = [barney, wilma, betty]  // 1

    return friends
}

func createFred() -> Person {
    let fred = Person(name: "Fred")

    let friends = createFredsFriends() // 2
    fred.friends = friends             // 3

    return fred
}

let fred = createFred()  // 4

print(fred.friends)  // [Barney, Wilma, Betty]
  • 在步骤 1,创建朋友数组。它被局部变量friends引用。

  • 1234563 /li>
  • 在第 3 步,对数组的第二个引用已分配给 fredfriends 属性。

  • 在第 4 步,createFred() 已返回,因此局部变量 friends 已消失,不再引用该数组。唯一的引用是在fred 对象的属性中,该对象由变量fred 持有。

所以数组创建了一次,创建了几个对它的引用,最后只有一个对数组的引用,所有这一切都是在没有一次复制操作的情况下完成的。


由于 Swift 数组是值类型并且在更改时被复制,所以您不能传递一个数组,然后期望在复制时更新原始数组。如果您需要该级别的功能,您可以为数组创建一个类包装器,然后始终通过该类的实例访问该数组。

这里我修改了前面的例子来展示它是如何工作的:

// Class to wrap array so that everyone references the same copy
class FriendsWrapper {
    var friends: [Person]

    init(friends: [Person]) {
        self.friends = friends
    }
}

class Person: CustomStringConvertible {
    let name: String
    var friendsWrapper: FriendsWrapper?

    init(name: String) {
        self.name = name
    }

    func addFriend(friend: Person) {
        if let wrapper = friendsWrapper {
            wrapper.friends.append(friend)
        } else {
            friendsWrapper = FriendsWrapper(friends: [friend])
        }
    }

    var description: String { return name }
}

func createFredsFriends() -> [Person] {
    let barney = Person(name: "Barney")
    let wilma = Person(name: "Wilma")
    let betty = Person(name: "Betty")
    let friends = [barney, wilma, betty]

    return friends
}

func createFred() -> Person {
    let fred = Person(name: "Fred")

    let friendsWrapper = FriendsWrapper(friends: createFredsFriends())
    fred.friendsWrapper = friendsWrapper

    // Add friend to Fred object
    fred.addFriend(Person(name: "Bam Bam"))

    // Copy of array in local friendsWrapper is updated
    print(friendsWrapper.friends)  // [Barney, Wilma, Betty, Bam Bam]

    return fred
}

let fred = createFred()

【讨论】:

  • 对不起,如果我需要通过引用传递一个数组,所以如果我更改第一个数组,第二个数组也会发生更改。是否可以这样做:mainView.categories = &categoriesData
  • 使用 Swift 数组是不可能做到这一点的。您可以创建一个基于类的包装器对象并将数组作为类对象的属性,然后将类对象传入。由于类始终作为引用保存,因此通过类访问时将引用相同的数组。像class friendsWrapper { var friends: [Person] } 这样的东西。然后你会像friendsWrapper.friends一样访问。
  • 感谢您的帮助
  • 我更新了答案以显示使用包装器的示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-02-27
  • 1970-01-01
  • 2013-11-10
  • 2015-11-02
  • 1970-01-01
  • 2012-12-02
  • 1970-01-01
相关资源
最近更新 更多