对象类型的变量作为数组行为不端

时间:2015-09-05 07:47:37

标签: arrays swift cocoa-touch uipickerview

环境XCode 6.4 Swift 2.something

我有两个简单的自定义类

class Stock {
    var ageArray = [3,6,9,12,15,18,24,30,36,42,48,54,60,66,72]  // in months
    var beastArray = ["Angus","Braford","Charolais","Droughtmaster","Euro","Hereford"]
    var breedArray = ["Calves","Vealers","Weaners","Heifers","Steers","Cows","Bulls"]
    var priceArray = [600.00,650.00,700.00,750.00,800.00,850.00,900.00,950.00,1000.00,]
}

class Sale {
    var age  : Int = 0
    var beast : String = " "
    var breed : String = " "
    var price : Double = 0.00
}

现在到我的视图控制器

我已经从Sale Class中实例化了一份报告。 ViewController包含所有这些报告的数组,因为我在nuremous地方教过,首先声明它并在viewDidLoad中实现它

class ViewController: UIViewController,  UIPickerViewDelegate, UIPickerViewDataSource  {

    @IBOutlet weak var picker: UIPickerView!

    var report = Sale()
    var sheets = Stock()

    var saleArray : [Sale] = [] // declaration

override func viewDidLoad() {
        super.viewDidLoad()

        saleArray = [Sale]()    // instantiating
    }

选择器的其他委托函数很甜蜜,不需要在这里显示所有这些,但这是两个类对象传递值的地方

func pickerView(picker: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

    switch(component) {
    case 0:
        report.breed = sheets.breedArray[row]
        break

    case 1:
        report.beast = sheets.beastArray[row]
        break

    case 2:
        report.age = sheets.ageArray[row]
        break

    default:
        report.price = sheets.priceArray[row]
        break
    }
}

和onscreeen按钮将它们加载到数组中

@IBAction func AcceptValues(sender:UIButton) {

    saleArray.append(report)
}

这就是它的全部内容。

这是在调试器中看到的结果,断点设置如下,经过3次左右,[0]应该有安格斯小牛,[1]有干旱小母牛

midnight colour scheme

所以问题是为什么saleArray会填满最后输入的n个实例?我知道我没有看过最后一次入场n次。但奇怪的是,报告的地址在7A19C000都是一样的。

我认为可能是编译器在viewDidLoad中的instatiaton之后无法推断出数组类型。检查各种教程和随附的代码或多或少地处理这个问题。这是标题的原因,我确信Swift可以保存除常规之外的一系列对象。

我甚至不花费购买Matt Neuberg的两本Matt Neuberg的书来检查如何设置一个Object Array,但是就像所有可用的材料一样,他们只讨论数组Int和Double以及String而已。有时最令人愤怒的错误是你最盯着你看的,我一直在追逐这个错误一周。

代码还有其他一点。

编辑: 感谢下面的两个贡献者,评论显示我做了什么使它工作。但我感觉它不优雅: 我还把股票作为结构。

class ViewController: UIViewController,  UIPickerViewDelegate, UIPickerViewDataSource  {

@IBOutlet weak var picker: UIPickerView!
@IBOutlet weak var textPanel: UITextView!

var sheets = Stock()
var saleArray : [Sale] = []

var localBreed = " "             // introduced some handover values
var localBeast = " "             // because report is out of scope
var localAge = 0                 // in the picker functions
var localPrice = 0.00

。 。

@IBAction func AcceptValues(sender:UIButton) { 

    var report = Sale()           // new reports instantiated here

    report.breed = localBreed     // and locals handover values to
    report.beast = localBeast     // report instance before adding
    report.age = localAge         // to array
    report.price = localPrice

    saleArray.append(report)
}

。 。

func pickerView(picker: UIPickerView, didSelectRow row: Int, inComponent component: Int) {

    switch(component) {
    case 0:
        localBreed = sheets.breedArray[row]
        break      
    case 1:
        localBeast = sheets.beastArray[row]
        break
    case 2:
        localAge = sheets.ageArray[row]
        break
    default:
        localPrice = sheets.priceArray[row]
        break
    }
}

1 个答案:

答案 0 :(得分:2)

我认为这是因为reportSale的单个实例。因此,每次选择新组合时 - 您都没有创建新的Sale项,而是更改与名为Sale的{​​{1}}单个实例关联的值。当您按下按钮时,它会添加对该单个report实例的另一个引用。

这些类对象通过引用传递 - 即,当您向report添加report时,它不会创建值的副本 - 而是传递对实际实例的引用。每次按下按钮,您都会添加对同一saleArray实例的引用。然后,当您使用选择器时,与该实例关联的值会发生变化。它一遍又一遍地是同一个实例。

您需要更改代码,以便为每个选择创建Sale的新实例。作为快速入侵,要对此进行测试,您可以在按钮中添加代码,根据所选值创建新的Sale实例 - 然后将其添加到Sale

ETA - 我注意到的另一件事:你在saleArraysaleArray两次实例化//declaration。虽然这不会引起您所描述的问题,但在潜在的情况下可能会导致问题。