-1

I've a NSObject class as follows:

class Number: NSObject {
    var number: Int = 0

    init(newNumber: Int) {
        self.number = newNumber
    }
}

And then I'm creating an array of this Number object as follows:

var numbersArr = [Number(newNumber: 1), Number(newNumber: 2)]

Now I want to change number property of an element of the existing array and append it as a new element. I'm doing it like:

var newItem = numbersArr[1]
newItem.number = 4
numbersArr(newItem)

I expect new value of numbersArr to be [1, 2, 4] but what I get is [1, 4, 4].

I understand that I'm changing the value of existing element instead of creating a new one and then appending it. But how can I achieve the desired result?

I can't initialize a new Number object and then append it. There are some other properties also in my actual NSObject class which needs to remain same.

Animesh Porwal
  • 557
  • 1
  • 10
  • 21
  • “But how can I achieve the desired result?” By creating a different Number object and appending it. “I can't initialize a new Number object and then append it.” Then you can’t achieve the desired result. – matt Dec 01 '18 at 02:01

3 Answers3

0

That's not possible. The nature of reference types is that changing a value for one reference changes it for all of them. Your only options are:

  1. Use a struct instead
  2. Initialize a new object

Assuming using a struct isn't an option, you might try adding a method to your class to copy all its values to a new object:

class Number: NSObject {
    var number: Int = 0

    init(newNumber: Int) {
        self.number = newNumber
    }

    func copy () -> Number {
        return Number(newNumber: self.number)
    }
}

And then:

let newItem = numbersArr[1].copy()
newItem.number = 4
numbersArr.append(newItem) // [1, 2, 4]
John Montgomery
  • 6,739
  • 9
  • 52
  • 68
0

You problem is a common one when dealing with reference type. You are index 1 and 2 of numbersArr point to the same object so when you modify one, you change the other too.

You need to make a deep copy:

class Number: NSObject, NSCopying {
    var number: Int = 0

    init(newNumber: Int) {
        self.number = newNumber
    }

    func copy(with zone: NSZone? = nil) -> Any {
        return Number(newNumber: self.number)
    }
}

var numbersArr = [Number(newNumber: 1), Number(newNumber: 2)]
let newItem = numbersArr[1].copy() as! Number
newItem.number = 4
numbersArr.append(newItem)
Code Different
  • 90,614
  • 16
  • 144
  • 163
  • I tried this before posting the question. This solution crashes when accessing `copy()` function with error `EXC_BAD_INSTRUCTION` – Animesh Porwal Dec 01 '18 at 01:38
0

Almost same as like Jhon Montgomery's solution, but small update on it.

func copy () -> Number {

    let number = Number(newNumber: self.number)

    //Copy your all other NSObject properties here
    //Example
    number.example = self.example

    return number
}

Now Try,

let newItem = numbersArr[1].copy() // Here it copies your number with all NSObject properties.
newItem.number = 4
numbersArr.append(newItem) // [1, 2, 4]
Natarajan
  • 3,241
  • 3
  • 17
  • 34