Обновление UILabel из обработчика UIAlertAction не работает в Swift 4 - PullRequest
0 голосов
/ 05 июня 2019

У меня есть подкласс UITableView в моем приложении для iOS (Swift 4, XCode 9). Эта таблица имеет одну строку, и я хочу, чтобы при нажатии на нее отображалось оповещение, получался ввод от пользователя, а затем обновлялась метка (lblUserFromPrefs) в таблице, когда пользователь нажимал «ОК» в оповещении. В настоящее время все работает отлично, кроме ярлыка не обновляется. Вот соответствующий код из моего подкласса UITableView:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print("Clicked section: \(indexPath.section) row: \(indexPath.row)")
    let alert = UIAlertController(title: "Username", message: "what is your name", preferredStyle: .alert)

    alert.addTextField { (textField) in
        textField.text = ""
    }
    alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [weak alert] (_) in
        let textField = alert!.textFields![0]
        if let text = textField.text {
            print("Text field: \(text)")
            DispatchQueue.main.async {
                self.lblUserFromPrefs.text = text
                print("label updated")
            }
        }
    }))

    DispatchQueue.main.async {
        self.present(alert, animated: true, completion: nil)
    }
}

Что происходит, когда я запускаю это, текст метки не изменяется при закрытии оповещения, а изменяется сразу же при повторном нажатии строки таблицы. Я не знаю, почему он ждет повторного щелчка по строке, чтобы обновить текст. Все операторы печати печатаются, когда я ожидаю (включая печать «ярлык обновлен» сразу после нажатия кнопки «ОК» оповещения), и они печатают правильные вещи. Я знаю, что когда вы пытаетесь обновить пользовательский интерфейс из замыкания в фоновом потоке, вы должны использовать DispatchQueue.main.async {}, но я не уверен, почему он не обновляется, хотя я использую основной поток. Я попытался использовать DispatchQueue.main.async(execute: {}) и поставить self.lblUserFromPrefs.setNeedsDisplay() сразу после self.lblUserFromPrefs.text = "text". Есть идеи, что я делаю не так? Спасибо !!

Ответы [ 3 ]

0 голосов
/ 05 июня 2019

Попробуйте что-то вроде этого:

let alertController = UIAlertController.init(title: "Enter some text", message: nil, preferredStyle: .alert)
    alertController.addTextField { (textField) in

        // Text field configuration
        textField.placeholder = "Enter..."
        textField.text = ""
    }

    alertController.addAction(UIAlertAction.init(title: "Ok", style: .default, handler: { (action) in
        if (alertController.textFields?.first?.hasText)! {
            if let text = alertController.textFields?.first?.text {
                self.label.text = text // Update the value
            }
        } else {
            self.label.text = "" // Default value
        }
    }))

    self.present(alertController, animated: true, completion: nil) // Present alert controller
0 голосов
/ 07 июня 2019

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

import UIKit
import PlaygroundSupport

class MyViewController : UITableViewController {

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

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

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
    if cell == nil {
      cell = UITableViewCell()
    }
    cell!.textLabel?.text = "Hello World!"
    return cell!
  }

  override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    let cell = tableView.cellForRow(at: indexPath)
    cell?.textLabel?.text = "Hello Universe!"
  }
}
0 голосов
/ 05 июня 2019

Добавьте [weak self] к отправке следующим образом:

DispatchQueue.main.async { [weak self] in

}
...