#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 = ""
Теперь, я полагаю, вы хотите такого поведения:
- Нажмите ячейку в табличном представлении
- Присутствует
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.