Swift数组附加覆盖其他数组值 [英] Swift Array Append Overwriting Other Array Values

查看:113
本文介绍了Swift数组附加覆盖其他数组值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Swift的新手,但我并不擅长编码。我以为我会尝试制作一个小游戏。这是我在学习时喜欢做的事情。

I'm new to Swift, but I'm not new to coding. I thought I would try my hand at making a little game. It's something I like to do when learning.

这就是我正在做的事情。我首先调用一个初始化我的对象模板的方法

Here's what I'm doing. I start of by calling a method that initialized my "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的func。 update函数随机选择两个模板中的一个,向模板对象添加一些其他信息,执行其他逻辑,并将对象附加到我拥有的数组中。一切接近附加似乎都有效。我添加了各种断点,GameObject对象似乎正在填充正确。

I have a timer that runs a func named "update" every second. The "update" func randomly selects one of the two templates, adds some other information to the template object, does some other logic, and appends the object to an array I have. Everything up to the append seems to be working. I have added various breakpoints and the GameObject object seems to be getting populated correctly.

当我追加对象时,它会覆盖对象数组中的其他项。我无法弄明白。我尽可能地搜索了它,似乎找不到适合我的问题的东西。这是我的其余代码。

When I append the object it is overwriting other items in the objects array. I can't figure it out. I've googled it as much as possible, and can't really seem to find anything that fits my issue. Here's the rest of my code related to this.

这是ViewController的顶部,而viewDidLoad

This is the top of the ViewController and the 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 - the commented out/hard coded append works, but obviously not what I want

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

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

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

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
}

很抱歉这么长的帖子。我只是希望尽可能多地包含信息。我通常不会发布到这样的地方,因为我尽可能努力地找到解决方案。 swift文件也在Git上。

Sorry for such a lengthy post. I just wanted to include as much information as possible. I don't usually post to places like this, because I try as hard as possible to find the solution myself. The swift file is also on Git.

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

推荐答案

您的 objectTemplates 数组存储对两个 GameObject的引用 initializeObjectTemplates 中创建的实例。当您的计时器触发时,选择其中一个模板对象,修改它并将其添加到阵列中。但是,数组只是存储对添加到其中的对象的引用,并且您只有两个对象,即使您将这些对象多次添加到数组中。

Your objectTemplates array stores references to two GameObject instances that were created in initializeObjectTemplates. When your timer fires you select one of these 'template' objects, modify it and add it to the array. However, the array is merely storing references to the objects you add to it, and you only have two objects, even though you are adding those objects to the array multiple times.

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

When you call populateObjectTemplate you modify one of the two object templates, which means that all other entries in the array that refer to that particular template will reflect those modifications. You need populateObjectTemplate to return a new GameObject, using the information in the template;

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数组附加覆盖其他数组值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆