0

I have created a cities class, which consists of several City objects, each with specific data. Since the data is fixed, I want to assign it in the init() function of the Cities object.

// CASE 1 - ERROR

class Cities : NSObject {
   var cityList:[City]   
   override init() {
      cityList  = []
      let city = City()

      city.fill("LA" , "USA")
      self.cityList.append(city)
      city.fill("Amsterdam" ,"Netherlands")
      self.cityList.append(city)
      city.fill("Beijing" , "China")
      self.cityList.append(city)

Result: Beijing Beijing Beijing


// CASE 2 - CORRECT

class Cities : NSObject {
   var cityList:[City]
   override init() {
       cityList  = []
       var city:City

       city = City(name: "LA" ,country: "USA")
       self.cityList.append(city)
       city = City(name: "Amsterdam", country: "Netherlands")
       self.cityList.append(city)
       city = City(name: "Beijing" , country: "China")
       self.cityList.append(city)

Result: LA, Amsterdam, Beijing

When I run this first script, I get a nice Cities object and the array has 3 cities in it, all Beijing.

In the Correct case, the data is assigned by the init function of object City. Now everything works as expected.

In both cases I have created only one City object: city. Why is this difference in Swift behaviour? Using Apple Swift version 2.1

1
  • Consider if you can use a struct for this instead of a class, can you use value semantics instead of reference? Commented Nov 16, 2015 at 10:52

2 Answers 2

1

In Case 1 you have only created one City object, this is the line which create the object:

let city = City()

City is a class, which is a reference type. It means it points you to the same place in memory. Your first call to:

city.fill("LA" , "USA")

set the properties to 'LA' and 'USA', the second call

city.fill("Amsterdam" ,"Netherlands")

go to the same place in memory and override the properties with the new values and the same happens with the 3rd call which is the last call so you end up with the values. Your array cityList has three items which points to the same place in memory this is why you see the same object:

cityList[0] === cityList[1] === cityList[2]

In Case 2 every time you create new object you call the constructor, for example:

City(name: "LA" ,country: "USA")

Constructor allocate new memory address which ends up with completely new object, so every time you call:

City(name:...)

your city object points to different place in memory.

Sign up to request clarification or add additional context in comments.

3 Comments

That sounds logical.For the correct case. So by calling the constructor, I always create a new object. Does this also mean that the City object (LA) is deleted when I create Amsterdam. Or does it remain in memory but can not be used?
Yes, when you call constructor you create new object and in your example city will store new reference, which points to your new object and the old reference will be override. In your example you add it to the array so the reference count is incremented and you can still access it by calling for example cityList[0]. Bu if you wouldn't add it to the array the object would be deallocated.
Great explanation. Thanks
1

In first case you create single City object and then fill it with different data, but it is one object that you created it once and simply placed the three pointer to it in the array, when you call fill you change the data inside this single object and in the end of your init you have array with 3 pointers to one object that contains last data

In second case you create 3 different objects and add it to array

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.