How to pass array by reference without function ?

2019-05-10 18:37发布

问题:

I have this class:

class MainView:UIView{

    var categories:[Category]!

}

i want to set the categories arg, but i need to pass it by reference not value. because it's more efficient and better.

so if i did this:

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

then it pass it by value.

if i need to pass it by reference i could do that by using function inside the MainView()

class MainView:UIView{

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

    }

}

but if i don't want to use set function, How could i pass it by reference. e.g

mainView.categories = &categoriesData. but that doesn't work ?thanks

回答1:

Swift uses ARC (Automatic Reference Counting) when dealing with arrays, and it delays copying arrays until one of the copies is modified:

For example:

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)

At step 1 above, there is only one copy of [1, 2, 3, 4, 5] in memory, and a, b, and c are references to it.

When a is modified in step 2, Swift gives a and new copy of the array and b and c continue to reference the original array. So now there are 2 copies of the array in memory.


Let's look at a much more involved example:

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]
  • At step 1, the array of friends is created. It is referenced by the local variable friends.

  • This reference goes away when createFredsFriends() returns, and the only reference to the array is held then by the local variable friends at step 2. Ownership of the array has been passed.

  • At step 3, a second reference to the array has been assigned to the friends property of fred.

  • At step 4, createFred() has returned, so the local variable friends is gone and no longer references the array. The only reference is in the property of the fred object which is held by the variable fred.

So the array was created once, several references to it were created, and in the end there is a single reference to the array and all of this was done without a single copy operation.


Since Swift arrays are value types and copied when changed, you can't pass an array and then expect the original to be updated when the copy is. If you need that level of functionality, you can create a class wrapper for the array and then always access that array through the instance of that class.

Here I've modified the previous example to show how that would work:

// 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()