Răsfoiți Sursa

fix other observers, make removeObserver more resilient by using NSObjectProtocol (see docs/ for details)

B. Petersen 4 ani în urmă
părinte
comite
588850ff21

+ 10 - 16
DcShare/Controller/ChatListController.swift

@@ -11,8 +11,6 @@ class ChatListController: UITableViewController {
     let viewModel: ChatListViewModel
     let contactCellReuseIdentifier = "contactCellReuseIdentifier"
     weak var chatListDelegate: ChatListDelegate?
-    var keyboardAppearedObserver: Any?
-    var keyboardDisappearedObserver: Any?
 
     /// MARK - search
 
@@ -53,14 +51,14 @@ class ChatListController: UITableViewController {
     override func viewDidAppear(_ animated: Bool) {
         navigationItem.hidesSearchBarWhenScrolling = true
         let nc = NotificationCenter.default
-        keyboardAppearedObserver = nc.addObserver(self,
-                                                  selector: #selector(keyboardWillShow(_:)),
-                                                  name: UIResponder.keyboardWillShowNotification,
-                                                  object: nil)
-        keyboardDisappearedObserver = nc.addObserver(self,
-                                                     selector: #selector(keyboardWillHide(_:)),
-                                                     name: UIResponder.keyboardWillHideNotification,
-                                                     object: nil)
+        nc.addObserver(self,
+                       selector: #selector(keyboardWillShow(_:)),
+                       name: UIResponder.keyboardWillShowNotification,
+                       object: nil)
+        nc.addObserver(self,
+                       selector: #selector(keyboardWillHide(_:)),
+                       name: UIResponder.keyboardWillHideNotification,
+                       object: nil)
     }
 
     override func viewDidLoad() {
@@ -71,12 +69,8 @@ class ChatListController: UITableViewController {
     }
 
     override func viewDidDisappear(_ animated: Bool) {
-        if let keyboardAppearedObserver = keyboardAppearedObserver {
-            NotificationCenter.default.removeObserver(keyboardAppearedObserver)
-        }
-        if let keyboardDisappearedObserver = keyboardDisappearedObserver {
-            NotificationCenter.default.removeObserver(keyboardDisappearedObserver)
-        }
+        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
+        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
     }
 
     @objc func keyboardWillShow(_ notification: Notification) {

+ 13 - 19
deltachat-ios/Chat/ChatViewController.swift

@@ -14,9 +14,9 @@ class ChatViewController: UITableViewController {
     let chatId: Int
     var messageIds: [Int] = []
 
-    var msgChangedObserver: Any?
-    var incomingMsgObserver: Any?
-    var ephemeralTimerModifiedObserver: Any?
+    var msgChangedObserver: NSObjectProtocol?
+    var incomingMsgObserver: NSObjectProtocol?
+    var ephemeralTimerModifiedObserver: NSObjectProtocol?
     // isDismissing indicates whether the ViewController is/was about to dismissed.
     // The VC can be dismissed by pressing back '<' or by a swipe-to-dismiss gesture.
     // The latter is cancelable and leads to viewWillAppear is called in case the gesture is cancelled
@@ -24,8 +24,6 @@ class ChatViewController: UITableViewController {
     var isDismissing = false
     var isInitial = true
     var ignoreInputBarChange = false
-    var foregroundObserver: Any?
-    var backgroundObserver: Any?
 
     lazy var isGroupChat: Bool = {
         return dcContext.getChat(chatId: chatId).isGroup
@@ -408,15 +406,15 @@ class ChatViewController: UITableViewController {
             self.updateTitle(chat: self.dcContext.getChat(chatId: self.chatId))
         }
 
-        foregroundObserver = nc.addObserver(self,
-                                            selector: #selector(applicationDidBecomeActive(_:)),
-                                            name: UIApplication.didBecomeActiveNotification,
-                                            object: nil)
+        nc.addObserver(self,
+                       selector: #selector(applicationDidBecomeActive(_:)),
+                       name: UIApplication.didBecomeActiveNotification,
+                       object: nil)
 
-        backgroundObserver = nc.addObserver(self,
-                                            selector: #selector(applicationWillResignActive(_:)),
-                                            name: UIApplication.willResignActiveNotification,
-                                            object: nil)
+        nc.addObserver(self,
+                       selector: #selector(applicationWillResignActive(_:)),
+                       name: UIApplication.willResignActiveNotification,
+                       object: nil)
 
         // things that do not affect the chatview
         // and are delayed after the view is displayed
@@ -453,12 +451,8 @@ class ChatViewController: UITableViewController {
         if let ephemeralTimerModifiedObserver = self.ephemeralTimerModifiedObserver {
             nc.removeObserver(ephemeralTimerModifiedObserver)
         }
-        if let foregroundObserver = self.foregroundObserver {
-            nc.removeObserver(foregroundObserver)
-        }
-        if let backgroundObserver = self.backgroundObserver {
-            nc.removeObserver(backgroundObserver)
-        }
+        nc.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)
+        nc.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)
         audioController.stopAnyOngoingPlaying()
 
     }

+ 3 - 3
deltachat-ios/Controller/AccountSetupController.swift

@@ -5,12 +5,12 @@ import DcCore
 class AccountSetupController: UITableViewController, ProgressAlertHandler {
     private let dcContext: DcContext
     private var skipOauth = false
-    private var backupProgressObserver: Any?
-    var progressObserver: Any?
+    private var backupProgressObserver: NSObjectProtocol?
+    var progressObserver: NSObjectProtocol?
     var onProgressSuccess: VoidFunction? // not needed here
     var onLoginSuccess: (() -> Void)?
 
-    private var oauth2Observer: Any?
+    private var oauth2Observer: NSObjectProtocol?
 
     private let tagEmailCell = 0
     private let tagPasswordCell = 1

+ 3 - 3
deltachat-ios/Controller/ChatListController.swift

@@ -9,9 +9,9 @@ class ChatListController: UITableViewController {
     private let deadDropCellReuseIdentifier = "deaddrop_cell"
     private let contactCellReuseIdentifier = "contact_cell"
 
-    private var msgChangedObserver: Any?
-    private var msgsNoticedObserver: Any?
-    private var incomingMsgObserver: Any?
+    private var msgChangedObserver: NSObjectProtocol?
+    private var msgsNoticedObserver: NSObjectProtocol?
+    private var incomingMsgObserver: NSObjectProtocol?
 
     private weak var timer: Timer?
 

+ 1 - 1
deltachat-ios/Controller/QrPageController.swift

@@ -4,7 +4,7 @@ import DcCore
 class QrPageController: UIPageViewController, ProgressAlertHandler {
     private let dcContext: DcContext
     weak var progressAlert: UIAlertController?
-    var progressObserver: Any?
+    var progressObserver: NSObjectProtocol?
     var qrCodeReaderController: QrCodeReaderController?
 
     private var selectedIndex: Int = 0

+ 1 - 1
deltachat-ios/Controller/SettingsController.swift

@@ -32,7 +32,7 @@ internal final class SettingsViewController: UITableViewController, ProgressAler
 
     let documentInteractionController = UIDocumentInteractionController()
     weak var progressAlert: UIAlertController?
-    var progressObserver: Any?
+    var progressObserver: NSObjectProtocol?
 
     // MARK: - cells
 

+ 1 - 1
deltachat-ios/Controller/WelcomeViewController.swift

@@ -3,7 +3,7 @@ import DcCore
 
 class WelcomeViewController: UIViewController, ProgressAlertHandler {
     private let dcContext: DcContext
-    var progressObserver: Any?
+    var progressObserver: NSObjectProtocol?
     var onProgressSuccess: VoidFunction?
 
     private lazy var scrollView: UIScrollView = {

+ 1 - 1
deltachat-ios/Handler/ProgressAlertHandler.swift

@@ -3,7 +3,7 @@ import DcCore
 
 protocol ProgressAlertHandler: UIViewController {
     var progressAlert: UIAlertController? { get set }   // needs to be implemented as weak
-    var progressObserver: Any? { get set } // set to nil in viewDidDisappear
+    var progressObserver: NSObjectProtocol? { get set } // set to nil in viewDidDisappear
     func showProgressAlert(title: String, dcContext: DcContext)
     func updateProgressAlertValue(value: Int?)
     func updateProgressAlert(error: String?)

+ 2 - 2
deltachat-ios/Helper/NotificationManager.swift

@@ -5,8 +5,8 @@ import UIKit
 
 public class NotificationManager {
     
-    var incomingMsgObserver: Any?
-    var msgsNoticedObserver: Any?
+    var incomingMsgObserver: NSObjectProtocol?
+    var msgsNoticedObserver: NSObjectProtocol?
 
     init() {
         initIncomingMsgsObserver()

+ 12 - 0
docs/uiview-layout.md

@@ -140,6 +140,18 @@ a tricky part (see eg. [3]) seems to be to hold the correct type of rerences to
 tl;dr: post from main thread and also add/remove observers from main thread.
 on receiving, assume, things will block.
 
+## notification system: adding and removing observers
+
+- for the `addObserver()` variant returning an object
+  (overview at https://developer.apple.com/documentation/foundation/notificationcenter )
+  always save the object as `NSObjectProtocol` not as `Any?` -
+  otherwise you risk to mix addObserver() functions as also
+  the non-return variant can be saved as `Any?`
+  (Swift allows saving "no return type" as `Any?`)
+
+- call `removeObserver(self)` only in deinit,
+  otherwise use `removeObserver(self, name, obj)` or `removeObserver(obj)`
+
 
 ## some sources