【问题标题】:Swift Array Append Overwriting Other Array ValuesSwift Array Append 覆盖其他数组值
【发布时间】:2016-06-30 05:39:12
【问题描述】:

我是 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))

}

我有一个计时器,它每秒运行一个名为“update”的函数。 “更新”函数随机选择两个模板之一,向模板对象添加一些其他信息,执行一些其他逻辑,并将对象附加到我拥有的数组中。直到追加的一切似乎都在工作。我添加了各种断点,并且 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 - 注释掉/硬编码的追加有效,但显然不是我想要的

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 = $0.bottomChance <= rand
        let isBelow = $0.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
}

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

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

【问题讨论】:

  • 对其进行了编辑以使其看起来更好一些。我希望我的要求是有道理的。

标签: ios arrays swift append


【解决方案1】:

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

当您调用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
}

【讨论】:

  • 非常感谢!我仍然习惯于整个引用的事情。我猜 C# 编码让我在某些方面变得懒惰。
  • 我喜欢这个新的关键字。 ;)
猜你喜欢
  • 1970-01-01
  • 2014-08-22
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 2015-05-14
  • 1970-01-01
  • 2022-01-26
相关资源
最近更新 更多