Одинаковая ссылка для всех объектов в iOS Swift - PullRequest
0 голосов
/ 20 февраля 2019

В swift 4.2 я сталкиваюсь с проблемой при обработке двух объектов массива. Когда я удаляю объекты из другого массива, значения удаляются из всех объектов.

1) Ниже мое закрытие

func GetChatBotData(completion: @escaping (_ result: ChatV_1_Model) -> Void) {

    var ChatBotData : ChatV_1_Model! = nil
    ApiHelper.sharedSession.postLoacl("http://localhost:3000/posts/", postData: NSDictionary(), methodtype: Constant.API.httpGet) { (isError, data, errorDescription) in

        DispatchQueue.main.async(execute: {
            if isError == false {
                ChatBotData = ChatV_1_Model.init(fromDictionary: data!)
                completion(ChatBotData)
            }
            else {
                //completion("Error to get result" as AnyObject)
                completion(ChatBotData)
            }
        })
    }
}

Теперь В моем контроллере

var PKComponents = [Chatbot_V_1_DataModel]()
var ChatMessages = [Chatbot_V_1_DataModel]()

override func viewDidLoad() {
    super.viewDidLoad()

     GetChatBotData() {(result: ChatbotV_1_Model!) in
        print("Call Plans: \(result!)")

        self.PKComponents = result.data
        self.ChatMessages = result.data
        self.ChatMessages[0].component.removeAll()
    }

В Viewdidload я удаляю объекты из массива self.ChatMessages, но он также удаляет из всех объектов, таких как, PKComponents и result.data.

Примечание. Я видел, что ссылка на результат такая же, как у PKComponents и Chatmessages.

Как решить эту проблему?

Ответы [ 4 ]

0 голосов
/ 20 февраля 2019

Вот упрощенный пример, где я могу воспроизвести вашу проблему:

class Component {

}
class SomeData {
    var components: [Component]
    init(components : [Component]) {
        self.components = components
    }
}

class Result {
    var data: [SomeData]
    init(data: [SomeData]) {
        self.data = data
    }
}




let someData = SomeData(components: [Component()])
let result = Result(data: [someData])

//problem begins here
let pkCompent = result.data
var chatMsgs = result.data
print(pkCompent[0].components.count)
chatMsgs[0].components.removeAll()
print(pkCompent[0].components.count)

Чтобы избежать проблемы со ссылками, преобразуйте SomeData в struct

struct SomeData {
    var components: [Component]
    init(components : [Component]) {
        self.components = components
    }
}
0 голосов
/ 20 февраля 2019

У вас есть 2 предложения.

1- Глубокая копия.
2- Используйте struct вместо класса, так как его тип значения.

Использование глубокой копии - это простой пример, когда вы назначаете что-то новомуНапример, используйте этот способ.

// Deep copy
var foo = Foo()
var otherFoo  = Foo(foo)

, а не это.

var fee = foo // shallow copy still the same referance 

Примечание: это обрабатывается swift, вам не нужно добавлять какие-либо единицы в класс.

0 голосов
/ 20 февраля 2019
  • component - это то, из чего вы его удаляете, а не Array, если быть точным.

  • В то время как реализация массивов в swift использует Struct, который является типом значения, а не типом объекта, то, что содержит ваш массив, т.е. объект Chatbot_V_1_DataModel, также может бытькласс, таким образом, элементы, содержащиеся в вашем массиве, являются ссылками на объект типа Chatbot_V_1_DataModel.

  • способ обойти это можно, определив Chatbot_V_1_DataModel как struct, то есть тип значения ИЛИ, сделав глубокую копию вашего массива, а затем используя эту копиюв вашем замыкании, когда вы его модифицируете.

Я говорю о чем-то в этих строках:

var copie = arr.map{$0.mutableCopy()}

еще лучше:

var PKComponents = [Chatbot_V_1_DataModel]()
var ChatMessages = [Chatbot_V_1_DataModel]()

override func viewDidLoad() {
super.viewDidLoad()
 var copie = arr.map{$0.mutableCopy()} // use this copy now elsewhere!!!
 GetChatBotData() {(result: ChatbotV_1_Model!) in
    print("Call Plans: \(result!)")

    self.PKComponents = result.data
    self.ChatMessages = result.data
    self.ChatMessages[0].component.removeAll()
}
0 голосов
/ 20 февраля 2019

Это проблема глубокого копирования.Либо вы пишете полный инициализатор, который копирует все и создает новый объект и использует его вместо простого присваивания.Или используйте структуру вместо класса.Но в качестве быстрого решения вы можете явно скопировать только массив компонентов, например:

self.PKCOMPONENTS = results.data
self.PKCOMPONENTS.components = Array(results.data.components)
...