From 69b707af3e89f66a0e2da03ca5cac3eb9a5f5346 Mon Sep 17 00:00:00 2001
From: Tony Li <tony.li@automattic.com>
Date: Wed, 5 Jul 2023 10:13:09 +1200
Subject: [PATCH] Only observe text field change notification from the alert

---
 .../ChangeUsernameViewController.swift        | 45 ++++++++++++-------
 1 file changed, 30 insertions(+), 15 deletions(-)

diff --git a/WordPress/Classes/ViewRelated/Me/My Profile/Change Username/ChangeUsernameViewController.swift b/WordPress/Classes/ViewRelated/Me/My Profile/Change Username/ChangeUsernameViewController.swift
index 7c899e58b112..8dd57cb91311 100644
--- a/WordPress/Classes/ViewRelated/Me/My Profile/Change Username/ChangeUsernameViewController.swift	
+++ b/WordPress/Classes/ViewRelated/Me/My Profile/Change Username/ChangeUsernameViewController.swift	
@@ -1,3 +1,4 @@
+import Combine
 import WordPressAuthenticator
 
 class ChangeUsernameViewController: SignupUsernameTableViewController {
@@ -16,7 +17,12 @@ class ChangeUsernameViewController: SignupUsernameTableViewController {
         return saveItem
     }()
 
-    private weak var confirmationController: UIAlertController?
+    private var confirmationTextObserver: AnyCancellable?
+    private weak var confirmationController: UIAlertController? {
+        didSet {
+            observeConfirmationTextField()
+        }
+    }
 
     init(service: AccountSettingsService, settings: AccountSettings?, completionBlock: @escaping CompletionBlock) {
         self.viewModel = ChangeUsernameViewModel(service: service, settings: settings)
@@ -32,13 +38,6 @@ class ChangeUsernameViewController: SignupUsernameTableViewController {
         super.viewDidLoad()
         setupViewModel()
         setupUI()
-
-        NotificationCenter.default.addObserver(
-            self,
-            selector: #selector(handleTextDidChangeNotification(_:)),
-            name: UITextField.textDidChangeNotification,
-            object: nil
-        )
     }
 
     override func viewWillAppear(_ animated: Bool) {
@@ -166,19 +165,35 @@ private extension ChangeUsernameViewController {
         return alertController
     }
 
-    @objc func handleTextDidChangeNotification(_ notification: Foundation.Notification) {
-        guard notification.name == UITextField.textDidChangeNotification,
-              let confirmationController,
-              let textField = notification.object as? UITextField,
-              confirmationController.textFields?.contains(textField) == true
+    func observeConfirmationTextField() {
+        confirmationTextObserver?.cancel()
+        confirmationTextObserver = nil
+
+        guard let confirmationController,
+              let textField = confirmationController.textFields?.first
         else {
-            DDLogInfo("The notification is not sent from the text field within the change username confirmation prompt")
             return
         }
 
         // We need to add another condition to check if the text field is the username confirmation text field, if there
         // are more than one text field in the prompt.
-        precondition(confirmationController.textFields?.count == 1, "There should be only one text field in the prompt")
+        assert(confirmationController.textFields?.count == 1, "There should be only one text field in the prompt")
+
+        confirmationTextObserver = NotificationCenter.default
+            .publisher(for: UITextField.textDidChangeNotification, object: textField)
+            .sink(receiveValue: { [weak self] in
+                self?.handleTextDidChangeNotification($0)
+            })
+    }
+
+    func handleTextDidChangeNotification(_ notification: Foundation.Notification) {
+        guard notification.name == UITextField.textDidChangeNotification,
+              let confirmationController,
+              let textField = notification.object as? UITextField
+        else {
+            DDLogInfo("The notification is not sent from the text field within the change username confirmation prompt")
+            return
+        }
 
         let actions = confirmationController.actions.filter({ $0.title == Constants.Alert.change })
         precondition(actions.count == 1, "More than one 'Change username' action found")