Swift数组附加覆盖其他数组值

我是Swift的新手,但我并不陌生。 我想我会试着做一个小游戏。 这是我喜欢学习的东西。

这是我正在做的。 我开始通过调用一个方法来初始化我的“对象模板”

internal func initializeObjectTemplates(){ objectTemplates.append(GameObject(passed_x: 0, passed_y: 0, passed_max: 25, passed_min: 25, passed_points: 100, passed_img: "BeerGlass1", passedLengthOfTimeOnScreen: 5, passedBottomChance: 1, passedTopChance: 50, passedId: 0)) objectTemplates.append(GameObject(passed_x: 0, passed_y: 0, passed_max: 25, passed_min: 25, passed_points: 300, passed_img: "BeerGlass2", passedLengthOfTimeOnScreen: 2, passedBottomChance: 51, passedTopChance: 100, passedId: 0)) } 

我有一个计时器,每秒钟运行一个名为“更新”的func。 “更新”func随机select两个模板之一,向模板对象添加一些其他信息,做一些其他的逻辑,并追加到我有一个数组。 一切都追溯到似乎正在工作。 我添加了各种断点,并且GameObject对象似乎正在被正确填充。

当我追加对象时,它将覆盖对象数组中的其他项目。 我无法弄清楚。 我已经尽可能地search了它,而且似乎找不到适合我的问题的任何东西。 这是我的代码的其余与此有关。

这是ViewController和viewDidLoad的顶部

 internal var step = 0 internal var objects = [GameObject]() @IBOutlet weak var points: UILabel! internal var objectTemplates = [GameObject]() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. view.backgroundColor = UIColor.blackColor() initializeObjectTemplates() let timer = NSTimer(timeInterval: 1, target: self, selector: #selector(ViewController.update), userInfo: nil, repeats: true) NSRunLoop.currentRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes) //var i = 1 //while i <= 100{ // update() // i += 1 //} } 

更新Func – 注释掉/硬编码的附加工作,但显然不是我想要的

 internal func update(){ step += 1 //removeExpiredButtons() objects.append(populateObjectTemplate(selectObjectTemplate(), step: step)) //objects.append(GameObject(passed_x: 0, // passed_y: 0, // passed_max: 25, // passed_min: 25, // passed_points: 300, // passed_img: "BeerGlass2", // passedLengthOfTimeOnScreen: 2, // passedBottomChance: 51, // passedTopChance: 100, // passedId: step)) print("There are \(objects.count) items and the first item has an id of \(objects[0].id)") } 

这些是更新调用的方法

selectObjectTemplate

 func selectObjectTemplate() -> GameObject { let rand = Random.within(1...100) return objectTemplates.filter(){ let isAbove = $0.bottomChance <= rand let isBelow = $0.topChance >= rand return isAbove && isBelow }[0] } 

populateObjectTemplate

 func populateObjectTemplate(obj: GameObject, step: Int) -> GameObject { let widthBoundary = Float(self.view.frame.width - 20) let heightBoundary = Float(self.view.frame.height - 20) let placex = CGFloat(Random.within(20.0...widthBoundary)) obj.x = placex let placey = CGFloat(Random.within(50.0...heightBoundary)) obj.y = placey obj.expiration = obj.lengthOfTimeOnScreen + step obj.id = step obj.button = populateObjectButton(obj) return obj } 

populateObjectButton

 func populateObjectButton(obj: GameObject) -> UIButton { let button = UIButton(type: UIButtonType.Custom) let image = UIImage(named: obj.img) button.setBackgroundImage(image, forState: UIControlState.Normal) button.frame = CGRectMake(obj.x, obj.y, obj.minSize, obj.minSize) button.layer.cornerRadius = 0.5 * button.bounds.size.width button.layer.masksToBounds = true button.addTarget(self, action: #selector(ViewController.objectTapped(_:)), forControlEvents: .TouchUpInside) button.tag = obj.id self.view.addSubview(button) return button } 

对不起,这么长的post。 我只是想包括尽可能多的信息。 我通常不会这样的地方,因为我尽可能努力自己find解决scheme。 Swift文件也在Git上。

https://github.com/JoeBrewing/TapGlassMasterChallenge/blob/master/Glass%20Tap%20Master%20Challenge/ViewController.swift

您的objectTemplates数组存储对在initializeObjectTemplates中创build的两个GameObject实例的引用。 当你的计时器激发你select这些“模板”对象之一,修改它并将其添加到数组。 但是,该数组仅仅存储对添加到其中的对象的引用,并且只有两个对象,即使将这些对象多次添加到数组中也是如此。

调用populateObjectTemplate您可以修改两个对象模板之一,这意味着引用该特定模板的数组中的所有其他条目都将反映这些修改。 你需要使用populateObjectTemplate来返回一个新的GameObject ,使用模板中的信息;

 func populateObjectTemplate(obj: GameObject, step: Int) -> GameObject { let newGameObject=GameObject(passed_x: 0, passed_y: obj.passed_y, passed_max: obj.passed_max, passed_min: obj.passed_min, passed_points: obj.passed_points, passed_img: obj.passed_img, passedLengthOfTimeOnScreen: obj.passedLengthOfTimeOnScreen, passedBottomChance: obj.passedBottomChance, passedTopChance: obj.passedTopChance, passedId: obj.passedId) let widthBoundary = Float(self.view.frame.width - 20) let heightBoundary = Float(self.view.frame.height - 20) let placex = CGFloat(Random.within(20.0...widthBoundary)) newGameObject.x = placex let placey = CGFloat(Random.within(50.0...heightBoundary)) newGameObject.y = placey newGameObject.expiration = obj.lengthOfTimeOnScreen + step newGameObject.id = step newGameObject.button = populateObjectButton(obj) return newGameObject }