Swift 数组追加覆盖其他数组值
Swift Array Append Overwriting Other Array Values
我是 Swift 的新手,但我对编码并不陌生。我想我会尝试做一个小游戏。这是我在学习时喜欢做的事情。
这就是我正在做的。我首先调用一个初始化 "object templates"
的方法
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))
}
我有一个计时器,每秒运行一个名为 "update" 的函数。 "update" func 随机选择两个模板之一,向模板对象添加一些其他信息,执行一些其他逻辑,并将该对象附加到我拥有的数组中。 append 之前的所有内容似乎都在工作。我添加了各种断点,GameObject 对象似乎得到了正确填充。
当我追加对象时,它会覆盖对象数组中的其他项目。我想不通。我已经尽可能多地用谷歌搜索了它,但似乎真的找不到适合我的问题的任何东西。这是我与此相关的其余代码。
这是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
//}
}
Update Func - 注释 out/hard 编码的追加有效,但显然不是我想要的
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)")
}
这些是更新调用的方法
选择对象模板
func selectObjectTemplate() -> GameObject {
let rand = Random.within(1...100)
return objectTemplates.filter(){
let isAbove = [=14=].bottomChance <= rand
let isBelow = [=14=].topChance >= rand
return isAbove && isBelow
}[0]
}
填充对象模板
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
}
填充对象按钮
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。我只是想包含尽可能多的信息。我通常 post 不去这样的地方,因为我尽可能努力地自己寻找解决方案。 swift 文件也在 Git.
上
您的 objectTemplates
数组存储对在 initializeObjectTemplates
中创建的两个 GameObject
实例的引用。当您的计时器触发您 select 这些 'template' 对象之一时,修改它并将其添加到数组中。但是,该数组仅存储对您添加到其中的对象的引用,并且您只有两个对象,即使您多次将这些对象添加到数组中也是如此。
当您调用 populateObjectTemplate
时,您修改了两个对象模板之一,这意味着数组中引用该特定模板的所有其他条目将反映这些修改。您需要 populateObjectTemplate
到 return 一个新的 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
}
我是 Swift 的新手,但我对编码并不陌生。我想我会尝试做一个小游戏。这是我在学习时喜欢做的事情。
这就是我正在做的。我首先调用一个初始化 "object templates"
的方法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))
}
我有一个计时器,每秒运行一个名为 "update" 的函数。 "update" func 随机选择两个模板之一,向模板对象添加一些其他信息,执行一些其他逻辑,并将该对象附加到我拥有的数组中。 append 之前的所有内容似乎都在工作。我添加了各种断点,GameObject 对象似乎得到了正确填充。
当我追加对象时,它会覆盖对象数组中的其他项目。我想不通。我已经尽可能多地用谷歌搜索了它,但似乎真的找不到适合我的问题的任何东西。这是我与此相关的其余代码。
这是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
//}
}
Update Func - 注释 out/hard 编码的追加有效,但显然不是我想要的
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)")
}
这些是更新调用的方法
选择对象模板
func selectObjectTemplate() -> GameObject {
let rand = Random.within(1...100)
return objectTemplates.filter(){
let isAbove = [=14=].bottomChance <= rand
let isBelow = [=14=].topChance >= rand
return isAbove && isBelow
}[0]
}
填充对象模板
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
}
填充对象按钮
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。我只是想包含尽可能多的信息。我通常 post 不去这样的地方,因为我尽可能努力地自己寻找解决方案。 swift 文件也在 Git.
上您的 objectTemplates
数组存储对在 initializeObjectTemplates
中创建的两个 GameObject
实例的引用。当您的计时器触发您 select 这些 'template' 对象之一时,修改它并将其添加到数组中。但是,该数组仅存储对您添加到其中的对象的引用,并且您只有两个对象,即使您多次将这些对象添加到数组中也是如此。
当您调用 populateObjectTemplate
时,您修改了两个对象模板之一,这意味着数组中引用该特定模板的所有其他条目将反映这些修改。您需要 populateObjectTemplate
到 return 一个新的 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
}