Arrays 作为数组的对象类型变量行为不正常

Arrays 作为数组的对象类型变量行为不正常,arrays,swift,cocoa-touch,uipickerview,Arrays,Swift,Cocoa Touch,Uipickerview,环境XCode 6.4 Swift 2.0 我有两个简单的自定义类 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","Vealer

环境XCode 6.4 Swift 2.0

我有两个简单的自定义类

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,]
}

现在转到我的视图控制器

我已经从Sale类实例化了一个报表。ViewController保存着我在许多地方学习的所有这些报告的数组,首先声明它,然后在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
    }
}
一个屏幕上的按钮将它们加载到一个数组中

@IBAction func AcceptValues(sender:UIButton) {

    saleArray.append(report)
}
就这些

这是在调试器中看到的结果,[0]假设有安格斯犊牛,[1]有Droughtmaster小母牛,经过3次调试器后,断点设置如下

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

我想可能是编译器在viewDidLoad中安装后无法推断数组类型。检查各种教程和随它们提供的代码时,或多或少会像我上面所说的那样处理这个问题。这就是标题的原因,我敢肯定斯威夫特可以容纳一系列的对象,而不是通常的对象

我甚至花钱购买了Matt Neuberg的两本书,而不是一本,只是为了检查如何设置对象数组,但就像所有可用的材料一样,它们只讨论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
。 .

。 .


我认为这是因为
report
Sale
的一个单一实例。因此,每次您选择一个新的组合-您不是在创建一个新的
Sale
项目,而是在更改与名为
report
Sale
的单个实例相关联的值。当您按下该按钮时,它会向单个
报告
实例添加另一个引用

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

您需要更改代码,以便为每个选择创建一个新的
Sale
实例。为了测试这一点,您可以在按钮中添加代码,根据选定的值创建一个新的
Sale
实例,然后将其添加到
saleArray


ETA-我注意到的另一件事是:您正在两次实例化
saleArray
——在
//声明中和
viewDidLoad()
中。虽然这并没有导致您描述的问题,但在潜在情况下可能会导致问题。

我需要一些时间来解决这个问题。另一种获得您可能期望的行为的方法是将Sale更改为struct(可能还有Stocks)。您将它们视为值,因此只需将它们设置为值而不是引用。不清楚为什么Stocks是一个类(或者为什么它甚至是它自己的一种类型,而不仅仅是4个常量数组)。按照这样做的方式,您不需要不断添加新数组。您只需要一个数组和多个
报表
项,即
销售
对象的多个实例。然后您的
saleArray
将包含例如
[report01、report02、report03…等]
。但是你也应该注意Rob Napier关于使用结构而不是类的说法。@simons我终于做到了这一点(在上面编辑),但如果有一种更干净的方法不使用中间值,我也不会感到惊讶。在其他项目中,你的评论在许多其他方面得到了证明。也要感谢罗布·纳皮尔。
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
    }
}