Передача индекса выбранной строки другому ViewController

#swift #xcode #indexpath

#swift #xcode #indexpath

Вопрос:

У меня есть вопрос, касающийся передачи индекса (MyIndex) из TableView в другой ViewController. Я опубликовал приведенный ниже код. Хорошая новость: когда я запускаю код, индекс передается другому Viewcontroller. Плохая новость: это не тот индекс, который я ожидал. (Когда я распечатываю myindex в Viewcontroller с помощью TableView, все работает нормально. Если я передам MyIndex другому ViewController, индекс будет перепутан…

Цель: мой TableView состоит из 18 строк (каждое отверстие в строке). Когда я нажимаю на строку, открывается другой Viewcontroller. В этом VieController имя выбранной строки должно отображаться сверху. Моя идея состояла в том, чтобы передать индекс каждой строки другому Viewcontroller, но это работает некорректно.

Кто-нибудь может мне помочь?

 import UIKit
var holes = ["Hole 1","Hole 2","Hole 3","Hole 4","Hole 5","Hole 6","Hole 7","Hole 8", "Hole 9","Hole 10","Hole 11","Hole 12","Hole 13","Hole 14","Hole 15","Hole 16","Hole 17","Hole 18"]
var myIndex = 0

class OverViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    // Label
    @IBOutlet weak var BackButton: UIButton!
    @IBOutlet weak var ScoreButton: UIButton!
    @IBOutlet weak var OverviewLabel: UILabel!
    

    @IBOutlet weak var tableView: UITableView!
    

    override func viewDidLoad() {
           super.viewDidLoad()
    }
    
    
    @IBAction func BackToStartScreen(_ sender: UIButton) {
        performSegue(withIdentifier: "BackToStart", sender: self)
    }
    
    @IBAction func GoToResultScreen(_ sender: UIButton) {
        performSegue(withIdentifier: "GoToResult", sender: self)
    }
    
        
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return holes.count
    }
        
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            cell.textLabel?.text = holes[indexPath.row]
            return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        myIndex = indexPath.row
        performSegue(withIdentifier: "GoToScore", sender: self)
        
    }
  
}
 

И ScoreViewController:

 import UIKit



class ScoreViewController: UIViewController {
    var score = 0
    var fairwayhits = 0
    var greeninregulation = 0
    var putts = 0
    var text = ""
        
    // Variable Deklaration
    var CurrentScore = 0
    var CurrentFairwayHits = 0
    var CurrentGreenInRegulations = 0
    var CurrentPutts = 0

    
    
    // Bar Label
    @IBOutlet weak var BackLabel: UIButton!
    @IBOutlet weak var TitleLabel: UILabel!
    
    // Score Elements
    @IBOutlet var ScoreLabel: UILabel!
    @IBOutlet var ScoreStepper: UIStepper!
    @IBOutlet var ScoreResultLabel: UILabel!
    @IBOutlet var ScoreFrameLabel: UILabel!
    
    // Fairway Elements
    @IBOutlet var FairwayLabel: UILabel!
    @IBOutlet var FairwaySwitch: UISwitch!
    @IBOutlet var FairwayResultLabel: UILabel!
    @IBOutlet var FairwayFrameLabel: UILabel!
    
    // Green Elements
    @IBOutlet var GreenLabel: UILabel!
    @IBOutlet var GreenSwitch: UISwitch!
    @IBOutlet var GreenResultLabel: UILabel!
    @IBOutlet var GreenFrameLabel: UILabel!
    
    // Putt Elements
    @IBOutlet var PuttLabel: UILabel!
    @IBOutlet var PuttStepper: UIStepper!
    @IBOutlet var PuttResultLabel: UILabel!
    @IBOutlet var PuttFrameLabel: UILabel!
    
    // Save Button
    @IBOutlet var SaveButton: UIButton!
    
    // Back Button
    @IBAction func BackButtonPressed(_ sender: UIButton) {
        performSegue(withIdentifier: "BackToOverview", sender: self)
    }
    
    // Score Stepper
    @IBAction func ScoreStepperPressed(_ sender: UIStepper) {
        ScoreResultLabel.text = Int(sender.value).description
    }
    
    // Fairway Switch
    @IBAction func FairwaySwitchPressed(_ sender: UISwitch) {
        if FairwaySwitch.isOn {
            CurrentFairwayHits = 1
            FairwayResultLabel.text = "X"
        } else {
            CurrentFairwayHits = 0
            FairwayResultLabel.text = "-"
        }
    }
    
    // Green Switch
    @IBAction func GreenSwitchPressed(_ sender: UISwitch) {
        if GreenSwitch.isOn {
            CurrentGreenInRegulations = 1
            GreenResultLabel.text = "X"
        } else {
            CurrentGreenInRegulations = 0
            GreenResultLabel.text = "-"
        }
    }
    

    // Putt Stepper
    @IBAction func PuttStepperPressed(_ sender: UIStepper) {
        PuttResultLabel.text = Int(sender.value).description
    }
    
    
    // Save Button
    @IBAction func SaveButtonPressed(_ sender: UIButton) {
        if Int(PuttResultLabel.text!)! >= Int(ScoreResultLabel.text!)! {
            showAlert()
        } else {
        score = score   Int(ScoreResultLabel.text!)!
        fairwayhits = fairwayhits   CurrentFairwayHits
        greeninregulation = greeninregulation   CurrentGreenInRegulations
        putts = putts   Int(PuttResultLabel.text!)!
        
        print(score)
        print(fairwayhits)
        print(greeninregulation)
        print(putts)
            
        performSegue(withIdentifier: "ShowResult", sender: self)
        }
    }
    
    
    func showAlert() {
        let alert = UIAlertController(title: "Ops, something went wrong", message: "The number of putts must be smaller than your score!", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: { action in print("tapped Dismissed")}))
        
        present(alert, animated: true)
    }

    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if SaveButton.isTouchInside,
           let resultVC = segue.destination as? ResultViewController
            {

            CurrentScore = score /// get the current cell's text
            CurrentPutts = putts
            resultVC.score = resultVC.score   String((resultVC.ScoreResultLabel.text!))
            resultVC.fairway = String(fairwayhits)
            resultVC.green = String(greeninregulation)
            resultVC.putt = String(putts)
            
            
               }
    }
    
    

    override func viewDidLoad() {
        
        super.viewDidLoad()

        ScoreStepper.wraps = true
        ScoreStepper.autorepeat = true
        ScoreStepper.minimumValue = 1
        ScoreStepper.maximumValue = 20
        
        PuttStepper.wraps = true
        PuttStepper.autorepeat = true
        PuttStepper.minimumValue = 0
        PuttStepper.maximumValue = 20
        

        TitleLabel.text = text
    
    }
}
 

И контроллер представления результата:

 

class ResultViewController: UIViewController {
    
    var score = ""
    var fairway = ""
    var green = ""
    var putt = ""
    

    @IBOutlet weak var TitleLabel: UILabel!
    @IBOutlet weak var BackButton: UIButton!
    @IBOutlet weak var ShareButton: UIButton!
    
    // Score Label
    @IBOutlet weak var ScoreLabel: UILabel!
    @IBOutlet weak var ScoreResultLabel: UILabel!
    @IBOutlet weak var ScoreFrameLabel: UILabel!
    
    // Fairway Label
    @IBOutlet weak var FairwayLabel: UILabel!
    @IBOutlet weak var FairwayResultLabel: UILabel!
    @IBOutlet weak var FairwayFrameLabel: UILabel!
    
    // Green Label
    @IBOutlet weak var GreenLabel: UILabel!
    @IBOutlet weak var GreenResultLabel: UILabel!
    @IBOutlet weak var GreenFrameLabel: UILabel!
    
    // Putt Label
    @IBOutlet weak var PuttLabel: UILabel!
    @IBOutlet weak var PuttResultLabel: UILabel!
    @IBOutlet weak var PuttFrameLabel: UILabel!
    
    // Back Button Action
    @IBAction func BackButtonPressed(_ sender: UIButton) {
        performSegue(withIdentifier: "BackToOverview", sender: self)
        
    }


        
    override func viewDidLoad() {
        super.viewDidLoad()

        ScoreResultLabel.text = "(score)"
        FairwayResultLabel.text = "(fairway)"
        GreenResultLabel.text  = "(green)"
        PuttResultLabel.text = "(putt)"
        
        
    }
    

 

}
 

Комментарии:

1.Сохраните свой var holes и var myIndex = 0 внутри OverViewController.

2. Затем в вашем другом контроллере представления установите var text и установите это внутри prepare(for:sender:) , что-то вроде if let nextViewController = segue.destination as? NextViewController { nextViewController.text = holes[myIndex] }

3. Можете ли вы объяснить свое предложение немного подробнее?

4. Конечно. Можете ли вы опубликовать свой код для ScoreViewController / контроллера представления, который вы открываете?

5. Хорошо, я опубликовал код ScoreViewController выше.

Ответ №1:

Первое: вы не хотите иметь переменные вне классов. Конечно, вы можете получить к ним доступ из всех ваших классов. Но это не очень хорошая практика, и вы столкнетесь с ошибками состояния.

Итак, замените

 var holes = ["Hole 1","Hole 2","Hole 3","Hole 4","Hole 5","Hole 6","Hole 7","Hole 8", "Hole 9","Hole 10","Hole 11","Hole 12","Hole 13","Hole 14","Hole 15","Hole 16","Hole 17","Hole 18"]
var myIndex = 0

class OverViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
 

с

 class OverViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    var holes = ["Hole 1","Hole 2","Hole 3","Hole 4","Hole 5","Hole 6","Hole 7","Hole 8", "Hole 9","Hole 10","Hole 11","Hole 12","Hole 13","Hole 14","Hole 15","Hole 16","Hole 17","Hole 18"]
    var myIndex = 0
 

А также заменить

 var score = 0
var fairwayhits = 0
var greeninregulation = 0
var putts = 0

var text = ""

class ScoreViewController: UIViewController {
 

с

 class ScoreViewController: UIViewController {
    var score = 0
    var fairwayhits = 0
    var greeninregulation = 0
    var putts = 0

    var text = ""
 

Теперь, я полагаю, вы хотите такого поведения:

  1. Нажмите ячейку в табличном представлении
  2. Присутствует ScoreViewController , отображающий текст ячейки

Вы можете поместить это в свою prepareForSegue функцию:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard let selectedPath = tableView.indexPathForSelectedRow else { return }
    if 
        segue.identifier == "GoToScore",
        let scoreVC = segue.destination as? ScoreViewController
    {
        let currentText = holes[selectedPath.row] /// get the current cell's text
        scoreVC.text = currentText
    }
}
 

Редактировать: затем вы можете установить TitleLabel.text text свойство внутри viewDidLoad , например:

 class ScoreViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        TitleLabel.text = text /// right here!
    }   
}
 

Вы также должны сохранить все свойства, включая такие выходы, как TitleLabel , в нижнем регистре. Это просто соглашение, которое упрощает чтение вашего кода другими людьми.

 @IBOutlet weak var backLabel: UIButton!
@IBOutlet weak var titleLabel: UILabel!
 

Имейте в виду, что для изменения имени выхода вам нужно разорвать ссылку и повторно связать ее снова из раскадровки.

Комментарии:

1. Хорошо, спасибо за исправление кода до сих пор! Последний вопрос, не могли бы вы сказать мне, где именно в коде я могу изменить вывод «titleLabel» (ScoreViewController) на выбранную строку OverViewController?

2. Работает отлично! Спасибо! В моем исходном коде я суммировал значения score, fairways, green и putt для каждой лунки (например, счетчик). Я сохранил значения в глобальной переменной. Теперь у меня больше нет глобальных переменных. Как я могу использовать функциональность счетчика с помощью инструкции func prepare?

3. Вы можете сделать scoreVC.score = scoreVC.score Int(scoreVC.ScoreResultLabel.text!)!

4. Когда я добавляю ваш код, я получаю ошибку «Неожиданно найдено ноль …» в строке вашего предложения по коду: «scoreVC.score = scoreVC.score Int(scoreVC.ScoreResultLabel.text!)!» Как я могу это исправить.

5. Ах, извините, я забыл. Это потому ScoreResultLabel , что в то время все еще равно nil . Вы должны просто выполнить функцию счетчика из ScoreViewController.