【问题标题】:Can't access variables from another class?不能访问其他类的变量?
【发布时间】:2015-02-05 14:32:31
【问题描述】:

所以我有一个名为FoodListTable 类型为UITableViewController 的类 我还有一个变量可以查找数组中元素的总和:

var calorieTotal: Float {
    return calorieNumberArray.reduce(0 as Float) { $0 + Float($1) }
}

我做了一些测试,这个变量计算正确。但是,当我尝试在另一个名为 Menu 的类中使用它时,它的计算结果为 0.0。我试过这样做:

@IBAction func calculateButtonTappedMenu(sender: AnyObject) {
let foodListTableAccess = FoodListTable()
let dividend = foodListTableAccess.calorieTotal

但是当我这样做时,var calorieTotal 仍然计算为 0.0。我怎样才能解决这个问题?我对编程很陌生,所以请提供我需要修复它的所有代码。此外,如果需要,这里是两个类中的所有代码:

class FoodListTable: UITableViewController {
var calorieNumberArray = [0,0,0,0,0,0,0,0,0]
var foods = [Food]()
override func viewDidLoad() {
    super.viewDidLoad()
    self.foods = [Food(Name: "Small French Fries: 197 Cal."),Food(Name: "Cheeseburger: 359 Cal., One Patty"),Food(Name: "Cheese Pizza: 351 Cal., One Slice"),Food(Name: "Fried Chicken Breast: 320 Cal."),Food(Name: "Large Taco: 571 Cal."),Food(Name: "Hotdog: 315 Cal., With Ketchup"),Food(Name: "Tuna Sandwich: 287 Cal."),Food(Name: "1 Cup Vanilla Ice Cream: 290 Cal."),Food(Name: "1 1/2 Cup Vegetable Salad: 30 Cal.")]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.foods.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
    var food : Food
    food = foods[indexPath.row]
    cell.textLabel.text = food.Name
    tableView.deselectRowAtIndexPath(indexPath, animated: true)

    return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    if let cell = tableView.cellForRowAtIndexPath(indexPath) {
        if cell.accessoryType == .None {

            if indexPath.row == 0 {
                calorieNumberArray[0] = 197
            }
            if indexPath.row == 1 {
                calorieNumberArray[1] = 359
            }
            if indexPath.row == 2 {
                calorieNumberArray[2] = 351
            }
            if indexPath.row == 3 {
                calorieNumberArray[3] = 320
            }
            if indexPath.row == 4 {
                calorieNumberArray[4] = 571
            }
            if indexPath.row == 5 {
                calorieNumberArray[5] = 315
            }
            if indexPath.row == 6 {
                calorieNumberArray[6] = 287
            }
            if indexPath.row == 7 {
                calorieNumberArray[7] = 290
            }
            if indexPath.row == 8 {
                calorieNumberArray[8] = 30
            }
            cell.accessoryType = .Checkmark
        } else {

            if indexPath.row == 0 {
                calorieNumberArray[0] = 0
            }
            if indexPath.row == 1 {
                calorieNumberArray[1] = 0
            }
            if indexPath.row == 2 {
                calorieNumberArray[2] = 0
            }
            if indexPath.row == 3 {
                calorieNumberArray[3] = 0
            }
            if indexPath.row == 4 {
                calorieNumberArray[4] = 0
            }
            if indexPath.row == 5 {
                calorieNumberArray[5] = 0
            }
            if indexPath.row == 6 {
                calorieNumberArray[6] = 0
            }
            if indexPath.row == 7 {
                calorieNumberArray[7] = 0
            }
            if indexPath.row == 8 {
                calorieNumberArray[8] = 0
            }
            cell.accessoryType = .None
        }
    }
    println(calorieNumberArray)
    println(calorieTotal)
}
var calorieTotal: Float {
    return calorieNumberArray.reduce(0 as Float) { $0 + Float($1) }
}
}
class Menu: Calculator {

@IBOutlet weak var yourWeightTextFieldMenu: UITextField!
@IBOutlet weak var exerciseListPickerViewMenu: UIPickerView!
@IBOutlet weak var calculateButtonMenu: UIButton!
@IBOutlet weak var calculatorContainerMenu: UIView!
@IBOutlet weak var answer1LabelMenu: UILabel!

override func viewDidLoad() {
    calculatorContainerMenu.hidden = false
    answer1LabelMenu.hidden = true
    yourWeightTextFieldMenu.delegate = self
    exerciseListPickerViewMenu.delegate = self
    exerciseListPickerViewMenu.dataSource = self
    calculateButtonMenu.enabled = false
    yourWeightTextFieldMenu.addTarget(self, action:"yourWeightEditingChanged:", forControlEvents:.EditingChanged);
}
override func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let text = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
    if textField == yourWeightTextFieldMenu {
        yourWeightFilled = text.toInt() != nil
    }
    return true
}
override func textFieldShouldClear(textField: UITextField) -> Bool {
    calculateButtonMenu.enabled = false
    return true
}
@IBAction func yourWeightEditingDidEndMenu(sender: AnyObject) {
    yourWeightTextFieldMenu.resignFirstResponder()
    self.yourWeight = (self.yourWeightTextFieldMenu.text as NSString).floatValue
}
override func validateCalculateButton() {
    self.calculateButtonMenu.enabled = (self.yourWeightFilled)
}
@IBAction func yourWeightEditingChangedMenu(sender: AnyObject) {
    self.validateCalculateButton()
}
@IBAction func calculateButtonTappedMenu(sender: AnyObject) {
    calculatorContainerMenu.hidden = true
    answer1LabelMenu.hidden = false
    let foodListTableAccess = FoodListTable()
    let divisor = (yourWeight * exerciseCurrentValue)
    let dividend = foodListTableAccess.calorieTotal
    let result = (round(dividend / divisor))
    answer1LabelMenu.text = "It will take you about \(result) minutes to burn off those menu choices by performing that exercise."
    println("divisor: \(divisor), dividend: \(dividend), result: \(result)")
}
}

谢谢!

【问题讨论】:

  • 是的...问题是您正在创建类的新实例,而不是获取当前实例。你在使用 UINavigationController 吗?
  • "所以请提供我需要修复它的所有代码。" – 不。
  • 这个问题似乎是题外话,因为它是一个代码请求。
  • @TheParamagneticCroissant 老实说,该解决方案似乎需要大约 3 行代码。没那么严重。
  • OP,你是如何从 FoodListTable 过渡到 Menu 的?

标签: ios class variables swift reduce


【解决方案1】:

问题是您正在创建类的新实例,而不是获取当前实例。如果您实际上使用的是UINavigationController,并且正如您在评论中所说的那样,您立即从FoodListTable 转换为Menu,则类似以下代码的内容应该允许您访问当前启用的FoodListTable 的实例导航堆栈:

@IBAction func calculateButtonTappedMenu(sender: AnyObject) {

    let navigationController: UINavigationController = self.navigationController!
    let numberOfViewControllers = navigationController.viewControllers.count
    var foodListTableAccess: FoodListTable = navigationController.viewControllers[numberOfViewControllers - 2] as FoodListTable

    let dividend = foodListTableAccess.calorieTotal

}

编辑:如果您的代码实际上并非如您所想的那样使用 UINavigationController 结构化,但您实际上使用的是另一条评论中提到的故事板,那么您可以执行以下操作来传递视图控制器对象上一节课。

FoodListTable 视图控制器中,更新prepareToSegue 以共享您当前的FoodListTable 实例:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    // (Uncomment the if block and specify a segue if this isn't the
    // segue leading from your view controller.)
    //if segue.identifier == "yourSegueName" {
    let menu = segue.destinationViewController as Calculator
    menu.foodListTable = self;
    //}
}

然后在您的Menu 视图控制器中添加一个相应的类变量来保存FoodListTable 对象:

class TableViewController: UITableViewController {

    var foodListTable: FoodListTable!

这样你就可以像这样在Menu 中访问它的值:

@IBAction func calculateButtonTappedMenu(sender: AnyObject) {
    let dividend = foodListTable.calorieTotal
}

【讨论】:

  • 很抱歉,这是一个非常糟糕的答案。您假设FoodListTableMenu 低一级,并且该海报正在使用导航控制器。两者都不合理。即使您的假设是正确的,挖掘导航控制器的视图堆栈以提取信息也是解决此问题的最糟糕的解决方案。如果Menu 对象需要数据,那么它应该被传递到对象中,对象不应该为它扎根。
  • @DanielT。我不假设任何事情。 OP 在他的回答下的评论中说了这两件事:“我正在为 FoodListTable 使用 UINavigationController,并且我正在使用导航栏从 FoodListTable 转换到 Menu,如果这就是你的意思的话。对不起,如果我误解了你的问题,我只是编码的新手,我只是想学习一些东西。”
  • 没问题,我想我过去回答过你的一两个问题。 OO 编程的一个基本原则是……给对象他们需要的数据,不要强迫他们四处寻找。
  • @DanielT。我的?从不。
  • 嗯...嗯,我以前见过这个名字。无论如何,您的回答促使我在回答中添加了一个额外的段落以提供更多详细信息。
【解决方案2】:

我明白你在哪里说你是编程新手。我认为您正在编写的程序对于您的第一次尝试来说有点太复杂了。在完成这项任务之前,您可能应该花更多时间在操场上玩耍。

现在到手头的问题...想想calorieNumberArray,它以什么方法填充了必要的数据?创建FoodListTable 的新实例如何导致该数组被填充?不是。

您需要做的是将信息传递到您的Menu 对象中,而不是尝试将其从您的FoodListTable 中提取出来。具体操作方式取决于Menu 对象的创建方式以及FoodListTableMenu 之间的关系。

我建议您删除您在问题中发布的代码,而是添加足够的代码来向我们展示您如何创建 Menu 对象以及您如何对其进行控制。然后我们可以向您展示将数据从FoodListTable 传递到Menu 的最佳方式。

如果您手动将Menu 推送到堆栈中的某个位置,则在创建它之后将卡路里信息传递给它。如果您正在使用情节提要和转场,请在 prepareForSegue 方法中将信息传递给 Menu

【讨论】:

  • 是的,我明白了。基本上,我分离类的原因是因为 FoodListTable 类是 UITableViewController 的子类,而 Menu 是 ViewController 的子类,我无法将它们组合起来,因为 View Controller 和 UITableViewController 已经具有许多相同的属性。
  • 是的,我正在使用情节提要和转场。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-25
  • 1970-01-01
  • 1970-01-01
  • 2017-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多