In swift 4.2 I am facing the problem while handling the two array objects, When I am removing objects from another array, the values are removed from the all the objects.
1) Below is my closure
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)
}
})
}
}
Now In my controller
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()
}
In Viewdidload I am removing objects from self.ChatMessages array but it removes from all the objects like, PKComponents and result.data as well.
Note: I have seen the reference of the result is same as PKComponents and Chatmessages.
How to resolve this?
Here's the simplified example, where I can reproduce your problem:
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)
Inorder to avoid the reference issue, convert SomeData to struct
struct SomeData {
var components: [Component]
init(components : [Component]) {
self.components = components
}
}
This is the problem of deep copying. Either you write a complete initializer that copies everything and create a new object and use that instead of just assignment. Or use struct instead of class. But as a quick fix you can explicitly only copy the component array like this:
self.PKCOMPONENTS = results.data
self.PKCOMPONENTS.components = Array(results.data.components)
You have 2 suggestions.
1- Deep copy .
2- Use struct
instead of class since its value type.
Incase of deep copy this is a simple example, when you assign something to new instance use this way.
// Deep copy
var foo = Foo()
var otherFoo = Foo(foo)
rather than this.
var fee = foo // shallow copy still the same referance
Note: this is handled by swift you don't have to add any inits to the class.
component
is what you are removing it from and not the Array
to be precise.
While arrays implementation in swift is using a Struct
which is a value type and not a Object type, what your array is holding, ie Object of Chatbot_V_1_DataModel
might as well be a class thus, the elements held in your array are references to object of type Chatbot_V_1_DataModel.
the way you can work around this is by having Chatbot_V_1_DataModel
defined as a struct
thus, a value type OR by making a deep copy of you array and then using that copy in you closure as you modify it.
I am talking about something on these lines:
var copie = arr.map{$0.mutableCopy()}
better yet:
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()
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.