iOS Swift中所有对象的参考相同

时间:2019-02-20 17:20:25

标签: ios arrays swift closures

在Swift 4.2中,我在处理两个数组对象时遇到了问题,当我从另一个数组中删除对象时,值将从所有对象中删除。

1)以下是我的结束语

function multiplicationgame() {
  var GameSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet71");
  var x1 = GameSheet.getRange("A2");
  var x2 = GameSheet.getRange("B2");
  var x3 = GameSheet.getRange("A7");
  var x4=GameSheet.getRange("B7");

  // for generating a random number Math.floor((Math.random() * 10) + 1);
  var m1=Math.floor((Math.random() * 10) + 1);
  var m2=Math.floor((Math.random() * 10) + 1);
  x1.setValue(m1);
  x2.setValue(m2);
  SpreadsheetApp.flush();
  var ui = SpreadsheetApp.getUi();
  var response = ui.prompt('Multiplication', Utilities.formatString('%s x %s = ?',m1,m2 ), ui.ButtonSet.OK);
  // creates a temp halt in speardsheet execution till the answer is entered
  x3.setValue(response.getResponseText());
  SpreadsheetApp.flush();
  var Answer = GameSheet.getRange("A7").getValue();

  if (Answer == m1*m2) {
    x4.setValue('Thats correct! Well done');
  }else{
    x4.setValue('Thats wrong! Better luck next time');
  }
}

现在在我的控制器中

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)
            }
        })
    }
}

在Viewdidload中,我正在从self.ChatMessages数组中删除对象,但它也会从所有对象(如PKComponents和result.data)中删除。

注意:我已经看到结果的引用与PKComponents和Chatmessages相同。

如何解决这个问题?

4 个答案:

答案 0 :(得分:1)

这是简化的示例,在这里我可以重现您的问题:

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
    }
}

答案 1 :(得分:0)

这是深度复制的问题。您可以编写一个完整的初始化程序来复制所有内容并创建一个新对象,然后使用它而不是仅仅进行赋值。或者使用struct而不是class。但是,作为一种快速解决方案,您可以明确地仅复制组件数组,如下所示:

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

答案 2 :(得分:0)

您有2条建议。

1-深度复制。
2-使用struct代替类,因为其值类型。

如果是深度复制,这是一个简单的示例, 当您为新实例分配内容时,请使用这种方式。

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

而不是这个。

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

注意:这是通过快速处理而不必在类中添加任何init的。

答案 3 :(得分:0)

  • component是您要从中删除的内容,而不是Array要删除的对象 准确点。

  • 虽然数组的快速实现使用的是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()
}