1

I am having trouble understanding why the following code is replacing all of my array elements with the latest information when I am trying to just append it.

I have the following class:

class usersAvailable {
    var username = String()
    var userAvatar = UIImage()
}

I have the following variables defined to use the class:

//the array which will hold users available to follow
    var usersAvailableArray = [usersAvailable]()
    var aUser = usersAvailable()

to check my sanity I also have declared a 'regular' array to see if I am getting the right values:

var usersArray:[[String]] = [["",""]]

when i execute the following code:

func getAllUsers() {

        usersAvailableArray.removeAll(keepCapacity: true)
        usersArray.removeAll(keepCapacity: true)
        var query = PFQuery(className: "_User")
        query.findObjectsInBackgroundWithBlock {
            (objects: [AnyObject]?, error: NSError?) -> Void in
            if error == nil {
                for object in objects! {
                  self.aUser.username = object["username"] as! String
                    println("aUser.username before append: \(self.aUser.username)")
                    println(self.aUser)
                    self.usersAvailableArray.append(self.aUser)
                    self.usersArray.append([self.aUser.username])
                    println("first element of usersAvailableArray: \(self.usersAvailableArray.first?.username)")
                    println("last element of usersAvailableArray: \(self.usersAvailableArray.last?.username)")
                    println("number of elements currently in usersAvailableArray: \(self.usersAvailableArray.count)")
                    println("first element of usersArray: \(self.usersArray.first)")
                    println("last element of usersArray: \(self.usersArray.last)")
                    println("number of elements currently in usersArray: \(self.usersArray.count)")
 }

here is the console output I get:

aUser.username before append: joeBob
ParseStarterProject.usersAvailable
first element of usersAvailableArray: Optional("joeBob")
last element of usersAvailableArray: Optional("joeBob")
number of elements currently in usersAvailableArray: 1
first element of usersArray: Optional(["joeBob"])
last element of usersArray: Optional(["joeBob"])
number of elements currently in usersArray: 1
aUser.username before append: monkey
ParseStarterProject.usersAvailable
first element of usersAvailableArray: Optional("monkey")
last element of usersAvailableArray: Optional("monkey")
number of elements currently in usersAvailableArray: 2
first element of usersArray: Optional(["joeBob"])
last element of usersArray: Optional(["monkey"])
number of elements currently in usersArray: 2
aUser.username before append: support
ParseStarterProject.usersAvailable
first element of usersAvailableArray: Optional("support")
last element of usersAvailableArray: Optional("support")
number of elements currently in usersAvailableArray: 3
first element of usersArray: Optional(["joeBob"])
last element of usersArray: Optional(["support"])
number of elements currently in usersArray: 3

Why is my append of usersAvailableArray replacing every element in the array UsersAvailableArray?

1 Answer 1

2

You are passing data to the array by reference, and in every loop you change the value of the reference:

self.aUser.username = object["username"] as! String
self.usersAvailableArray.append(self.aUser)

Try to create a new user every time:

var newUser = usersAvailable()
newUser.username = object["username"] as! String
self.usersAvailableArray.append(newUser)

This is happening because the object you are append come from a class, from appe documentation:

Classes Are Reference Types

Unlike value types, reference types are not copied when they are assigned to a variable or constant, or when they are passed to a function. Rather than a copy, a reference to the same existing instance is used instead. You can see more about values and references in Swift

Another solution is to change your class to a struct, like below, structs different if classes make a copy of the value when it is passes instead pass a reference.

struct usersAvailable {
    var username = String()
    var userAvatar = UIImage()
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I turned it into a struct and everything is fine. Still a bit confused about WHY this worked - I will do some reading up on the differenct between reference and value types.
Basically structs create a copy of it self before is stored while for classes a reference to the class is pass instead its value, that is one of the major difference between classes and structs. Please don't forget to set the issue as solve by clicking the check on side of it and fell free to click the up arrow if you think I help you :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.