Как перейти к заполненной версии TableViewController (Swift)? - PullRequest
0 голосов
/ 16 мая 2018

Я создаю приложение для бронирования номеров для iOS в Xcode 9.3. Вот основной макет:

  • Первый TableViewController (TVC1): начинается пусто. Нажатие «+» выскакивает
  • Второй TableViewController (TVC2) с множеством полей для заполнения.

После нажатия кнопки «Готово» на TVC2 я возвращаюсь к TVC1, в котором теперь есть ячейка (стиль субтитров), содержащая вставленные детали.

Теперь я хотел бы нажать на указанную ячейку и вернуться к TVC2, чтобы проверить или изменить данные.
Я создал переход, но при нажатии я получаю ту же версию TVC2, что и при нажатии «+», а не заполненную.

Что я делаю не так?

Это код относительно TVC1, который мне нужно отредактировать:

import UIKit

class RegistrationTableViewController: UITableViewController {
    var registrations: [Registration] = []

override func viewDidLoad() {
    super.viewDidLoad()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return registrations.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "RegistrationCell", for: indexPath)

    let registration = registrations[indexPath.row]
    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .short

    cell.textLabel?.text = registration.firstName + " " + registration.lastName
    cell.detailTextLabel?.text = dateFormatter.string(from: registration.checkInDate) + " - " + registration.roomType.name

    return cell
}

@IBAction func unwindFromAddRegistration(unwindSegue: UIStoryboardSegue) {
    guard let addRegistrationTableViewController = unwindSegue.source as? AddRegistrationTableViewController,
        let registration = addRegistrationTableViewController.registration else { return }

    registrations.append(registration)
    tableView.reloadData()
}

// MARK: Challenge.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ViewReservationDetails" {


    }
}  

А вот код (TVC2), чтобы у вас было более или менее доступно все приложение.

import UIKit

class AddRegistrationTableViewController: UITableViewController, SelectRoomTypeTableViewControllerDelegate {
// MARK: Properties
let checkInDatePickerCellIndexPath = IndexPath(row: 1, section: 1)
let checkOutDatePickerCellIndexPath = IndexPath(row: 3, section: 1)

var isCheckInDatePickerShown: Bool = false {
    didSet {
        checkInDatePicker.isHidden = !isCheckInDatePickerShown
    }
}
var isCheckOutDatePickerShown: Bool = false {
    didSet {
        checkOutDatePicker.isHidden = !isCheckOutDatePickerShown
    }
}

var roomType: RoomType?
var registration: Registration? {
    guard let roomType = roomType else { return nil }

    let firstName = firstNameTextField.text ?? ""
    let lastName = lastNameTextField.text ?? ""
    let email = emailTextField.text ?? ""
    let checkInDate = checkInDatePicker.date
    let checkOutDate = checkOutDatePicker.date
    let numberOfAdults = Int(numberOfAdultsStepper.value)
    let numberOfChildren = Int(numberOfChildrenStepper.value)
    let hasWifi = wifiSwitch.isOn

    return Registration(firstName: firstName, lastName: lastName, emailAddress: email, checkInDate: checkInDate, checkOutDate: checkOutDate, numberOfAdults: numberOfAdults, numberOfChildren: numberOfChildren, roomType: roomType, wifi: hasWifi)
}

var selectedItem: Registration?

// MARK: Outlets
@IBOutlet weak var firstNameTextField: UITextField!
@IBOutlet weak var lastNameTextField: UITextField!
@IBOutlet weak var emailTextField: UITextField!

@IBOutlet weak var checkInDateLabel: UILabel!
@IBOutlet weak var checkInDatePicker: UIDatePicker!
@IBOutlet weak var checkOutDateLabel: UILabel!
@IBOutlet weak var checkOutDatePicker: UIDatePicker!

@IBOutlet weak var numberOfAdultsLabel: UILabel!
@IBOutlet weak var numberOfAdultsStepper: UIStepper!
@IBOutlet weak var numberOfChildrenLabel: UILabel!
@IBOutlet weak var numberOfChildrenStepper: UIStepper!

@IBOutlet weak var roomTypeLabel: UILabel!

@IBOutlet weak var wifiSwitch: UISwitch!

// MARK: Actions
@IBAction func datePickerValueChanged(_ sender: UIDatePicker) {
    updateDateViews()
}
@IBAction func stepperValueChanged(_ sender: UIStepper) {
    updateNumberOfGuests()
}
@IBAction func wifiSwitchChanged(_ sender: UISwitch) {
    // implemented later
}
@IBAction func cancelButtonTapped(_ sender: Any) {
    dismiss(animated: true, completion: nil)
}
// MARK: Methods
func updateDateViews() {
    checkOutDatePicker.minimumDate = checkInDatePicker.date.addingTimeInterval(86400)

    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .medium

    checkInDateLabel.text = dateFormatter.string(from: checkInDatePicker.date)
    checkOutDateLabel.text = dateFormatter.string(from: checkOutDatePicker.date)
}

func updateNumberOfGuests() {
    numberOfAdultsLabel.text = "\(Int(numberOfAdultsStepper.value))"
    numberOfChildrenLabel.text = "\(Int(numberOfChildrenStepper.value))"
}

func updateRoomType() {
    if let roomType = roomType {
        roomTypeLabel.text = roomType.name
    } else {
        roomTypeLabel.text = "Not Set"
    }
}

func didSelect(roomType: RoomType) {
    self.roomType = roomType
    updateRoomType()
}

override func viewDidLoad() {
    super.viewDidLoad()

    let midnightToday = Calendar.current.startOfDay(for: Date())
    checkInDatePicker.minimumDate = midnightToday
    checkInDatePicker.date = midnightToday

    updateDateViews()
    updateNumberOfGuests()
    updateRoomType()
}

// MARK: TableView Data
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    switch (indexPath.section, indexPath.row) {
    case (checkInDatePickerCellIndexPath.section, checkInDatePickerCellIndexPath.row):
        if isCheckInDatePickerShown {
            return 216.0
        } else {
            return 0.0
        }
    case (checkOutDatePickerCellIndexPath.section, checkOutDatePickerCellIndexPath.row):
        if isCheckOutDatePickerShown {
            return 216.0
        } else {
            return 0.0
        }
    default:
        return 44.0
    }
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)

    switch (indexPath.section, indexPath.row) {
    case (checkInDatePickerCellIndexPath.section, checkInDatePickerCellIndexPath.row - 1):
        if isCheckInDatePickerShown {
            isCheckInDatePickerShown = false
        } else if isCheckOutDatePickerShown {
            isCheckOutDatePickerShown = false
            isCheckInDatePickerShown = true
        } else {
            isCheckInDatePickerShown = true
        }

        tableView.beginUpdates()
        tableView.endUpdates()

    case (checkOutDatePickerCellIndexPath.section, checkOutDatePickerCellIndexPath.row - 1):
        if isCheckOutDatePickerShown {
            isCheckOutDatePickerShown = false
        } else if isCheckInDatePickerShown {
            isCheckInDatePickerShown = false
            isCheckOutDatePickerShown = true
        } else {
            isCheckOutDatePickerShown = true
        }

        tableView.beginUpdates()
        tableView.endUpdates()

    default:
        break
    }
}

// MARK: Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "SelectRoomType" {
        let destinationViewController = segue.destination as? SelectRoomTypeTableViewController
        destinationViewController?.delegate = self
        destinationViewController?.roomType = roomType
    }
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

}

Задача этого урока - начать отсюда и: "Обновите RegistrationTableViewController (TVC1) с помощью перехода, который позволяет пользователю выбирать и просматривать детали регистрации в AddRegistrationTableViewController (TVC2).

Надеюсь, это поможет найти правильное решение.

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Используйте этот код в tableView(_:didSelectRowAt:):

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
    performSegue(withIdentifier: "ViewReservationDetails", sender: indexPath)
}

Затем в prepare(for:sender:) в TVC1 вы передаете выбранный элемент registrations и обработчик завершения в TVC2, например:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "ViewReservationDetails" {
        if let destination = segue.destination as? AddRegistrationTableViewController, let indexPath = sender as? IndexPath {
            destination.registration = registrations[indexPath.row]
            destination.completionHandler = { (registration) in
                self.registrations.append(registration)
                self.tableView.reloadData()
            }
        }
    }
}

В TVC2 вы объявляете свойство completionHandler следующим образом:

var completionHandler: ((Registration) -> Void)?

и вы вызываете этот обработчик в viewWillDisappear:

completionHandler?(newRegistration)

с newRegistration является вновь созданным элементом для добавления в массив Registration. Таким образом, вам не понадобится раскрутка.

0 голосов
/ 16 мая 2018

Создайте свойство, скажем, selectedItem на экране TVC2.

var selectedItem: Registration?

Измените подготовку к ячейке ...

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

   if segue.identifier == "ViewReservationDetails" {

         let sourceCell = sender as! UITableViewCell

         if let indexPath = tableView.indexPath(for: sourceCell) {

            if let dest = segue.destination as? <#Destination view controller#> {

              dest.selectedItem = registrations[indexPath.row]
            }
         }
    }
 }

И, наконец, в контроллере представления назначения (с TVC2) вам нужно проверить selectedItem и присвоить значение в viewDidLoad: или где-либо еще.

 override func viewDidLoad() {
    super.viewDidLoad()

    if let  item = selectedItem {
        //here set value as you want to views

     }
}
...