Search code examples
iosswift3

update array index but its changing all index in IOS


here i am trying to update particular value in index but its updating all the index

class salarty  {

var sal_id                        :String = ""
var sal_amount             :String = ""
var sal_iScreated          :Bool = false

init(sal_id : String, sal_amount : String, sal_iScreated: Bool){

   self.sal_id                =  sal_id
   self.sal_amount     =  sal_id
   self.sal_iScreated =  sal_id

}
}

class Employee {

    let id: Int, firstName: String, lastName: String
    var salaryArray  :[salarty]  = [salarty]()


    init(id: Int, firstName: String, lastName: String, salaryArray: [salarty]) {
        self.id = id
        self.firstName = firstName
        self.lastName  = lastName
        self.salaryArray = salaryArray
    }
     }


array_SalaryDetails.append(salarty(sal_id : "2", sal_amount : "3000", sal_iScreated: false))

let employeeArray = [
    Employee(id: 1, firstName: "Jon", lastName: "Skeet",salaryArray :array_SalaryDetails),
    Employee(id: 2, firstName: "Darin", lastName: "Dimitrov",salaryArray :array_SalaryDetails),
    Employee(id: 4, firstName: "Hans", lastName: "Passant",salaryArray :array_SalaryDetails)
]

here i tried with some code its not working

Method 1 :

var model  = Employee[(indexPath?.section)!].salaryArray
        let model2 = model[(indexPath?.row)!]
        model = model.map{
            let mutableval = $0
            if $0.sal_id == model2.sal_id {
                mutableBook.sal_iScreated = !model2.sal_iScreated
            }
            return mutableval
        }

Method 2 :

    let model  = array_Main[(indexPath?.section)!].serviceArray
    let model2 = model[(indexPath?.row)!]

    model2.service_isSelected = !model2.service_isSelected

Solution

  • Thats because in Swift instance of class are passed by reference and not by value.

    So the salary array you created and passed to multiple Employee object they eventually had reference to same salary objects . So changing value of salary in any array in any Employee object would reflect change in all Employee objects

    Two possible solutions:

    Solution 1: Preferred solution

    Change salarty to be struct and not class and if possible change the spelling of salary as well :P

    struct salarty  {
            
            var sal_id                        :String = ""
            var sal_amount             :String = ""
            var sal_iScreated          :Bool = false
            
            init(sal_id : String, sal_amount : String, sal_iScreated: Bool){
                
                self.sal_id                =  sal_id
                self.sal_amount     =  sal_id
                self.sal_iScreated =  sal_iScreated
                
            }
        }
    

    Solution 2:

    Create a deep copy of salary array for each Employee before assigning.

    class salarty : NSObject, NSCopying  {
        func copy(with zone: NSZone? = nil) -> Any {
            let copy = salarty(sal_id: self.sal_id, sal_amount: self.sal_amount, sal_iScreated: self.sal_iScreated)
            return copy
        }
        
        
        var sal_id                        :String = ""
        var sal_amount             :String = ""
        var sal_iScreated          :Bool = false
        
        init(sal_id : String, sal_amount : String, sal_iScreated: Bool){
            
            self.sal_id                =  sal_id
            self.sal_amount     =  sal_id
            self.sal_iScreated =  sal_iScreated
            
        }
    }
    

    for each employee you can create a new array using either

        array_SalaryDetails.append(salarty(sal_id : "2", sal_amount : "3000", sal_iScreated: false))
        //salary array copy for first employee
        var firstEmployeearrayCopy = [salarty]()
        for salary in array_SalaryDetails {
            firstEmployeearrayCopy.append(salary.copy() as! salarty)
        }
        Employee(id: 1, firstName: "Jon", lastName: "Skeet",salaryArray : firstEmployeearrayCopy)
    
        //salary array copy for second employee
        var secondEmployeearrayCopy = [salarty]()
        for salary in array_SalaryDetails {
            secondEmployeearrayCopy.append(salary.copy() as! salarty)
        }
        Employee(id: 2, firstName: "Darin", lastName: "Dimitrov",salaryArray :secondEmployeearrayCopy)
    

    or you can create array again n again for each employee.

    In swift Array is passed by value but the objects (instance of class) in array will still be passed by reference as a result you will have to do all these workarounds :)

    Piece of Advice:

    Class names should start with capital letter. Only variable names follow camel casing.

    Hope it helps