title: Swift async await: how to use with several non async delegates?
body: <p>I have created this simple example, it is a <code>UITextField</code> with an autocompletion ability, displaying a table view showing asynchronous data that evolves as the user types in the text field.</p>
  <p><strong>TextField</strong></p>
  <pre><code>import UIKit
  
  protocol TextFieldDelegate {
      func autocompletedComponents(
          _ textField: TextField,
          _ components: @escaping ([String]) -&gt; Void
      )
  }
  
  class TextField: UITextField {
      var components: [String] = []
      var tableView = UITableView(frame: .zero)
      var autocompletionDelegate: TextFieldDelegate? { didSet { setupUI() } }
      
      // Actions
      @objc private func didUpdateText() {
          autocompletionDelegate?.autocompletedComponents(self) { [weak self] components in
              guard let weakSelf = self else {
                  return
              }
              weakSelf.components = components
              weakSelf.tableView.reloadData()
              weakSelf.updateUI()
          }
      }
      
      // Event
      override func becomeFirstResponder() -&gt; Bool {
          tableView.isHidden = false
          return super.becomeFirstResponder()
      }
      
      override func resignFirstResponder() -&gt; Bool {
          tableView.isHidden = true
          return super.resignFirstResponder()
      }
      
      // Init
      override init(frame: CGRect) {
          super.init(frame: frame)
          internalInit()
      }
      
      required init?(coder: NSCoder) {
          super.init(coder: coder)
          internalInit()
      }
      
      private func internalInit() {
          addTarget(
              self,
              action: #selector(didUpdateText),
              for: .editingChanged
          )
      }
      
      // UI
      private func setupUI() {
          tableView.dataSource = self
          tableView.delegate = self
          tableView.showsVerticalScrollIndicator = false
          tableView.removeFromSuperview()
          superview?.addSubview(tableView)
      }
      
      private func updateUI() {
          let tableViewHeight = Double(min(5, max(0, components.count))) * 44.0
          tableView.frame = CGRect(
              origin: CGPoint(
                  x: frame.origin.x,
                  y: frame.origin.y + frame.size.height
              ),
              size: CGSize(
                  width: frame.size.width,
                  height: tableViewHeight
              )
          )
      }
  }
  
  extension TextField: UITableViewDataSource, UITableViewDelegate {
      func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
          let cell = UITableViewCell()
          cell.textLabel?.text = components[indexPath.row]
          return cell
      }
      
      func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -&gt; CGFloat {
          44.0
      }
      
      func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
          components.count
      }
  }
  </code></pre>
  <p><strong>ViewController</strong></p>
  <pre><code>import MapKit
  import UIKit
  
  class ViewController: UIViewController {
      private var completion: (([MKLocalSearchCompletion]) -&gt; Void)?
      private var searchCompleter = MKLocalSearchCompleter()
      
      @IBOutlet weak var textField: TextField!
      
      override func viewDidLoad() {
          super.viewDidLoad()
          searchCompleter.delegate = self
          textField.autocompletionDelegate = self
      }
  }
  
  extension ViewController: TextFieldDelegate {
      func autocompletedComponents(
          _ textField: TextField,
          _ components: @escaping ([String]) -&gt; Void
      ) {
          if completion == nil {
              completion = { results in
                  components(results.map { $0.title })
              }
          }
          searchCompleter.queryFragment = textField.text ?? &quot;&quot;
      }
  }
  
  extension ViewController: MKLocalSearchCompleterDelegate {
      func completerDidUpdateResults(_ completer: MKLocalSearchCompleter) {
          completion?(completer.results)
      }
  }
  </code></pre>
  <p>In this example the view controller uses data from <code>MapKit</code>. Now I would like to get rid of the <code>@escaping</code> blocks and replace them with the new async/await syntax.</p>
  <p>I have started rewriting the <code>TextField</code> code:</p>
  <pre><code>protocol TextFieldDelegate {
      func autocompletedComponents(
          _ textField: TextField
      ) async -&gt; [String]
  }
  
  @objc private func didUpdateText() {
      Task {
          let autocompletedComponents = await autocompletionDelegate?.autocompletedComponents(self) ?? []
          components = autocompletedComponents
          tableView.reloadData()
          updateUI()
      }
  }
  </code></pre>
  <p>However I am stuck in the ViewController, because I don't know what to do with the completion block I was using until now.</p>
  <p>Thank you for your help</p>