Arrays 作为数组的对象类型变量行为不正常
环境XCode 6.4 Swift 2.0 我有两个简单的自定义类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
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
}
}