From 7a1e47cd26be0d99c7cc4ba1dafff61f98faaa2c Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 7 Dec 2017 10:33:27 -0500 Subject: [PATCH 1/3] Add asserts around Swift singletons. --- Signal/src/AppDelegate.m | 2 +- Signal/src/Jobs/MessageFetcherJob.swift | 4 +++ Signal/src/Models/AccountManager.swift | 4 +++ .../CallNotificationsAdapter.swift | 4 +++ .../UserNotificationsAdaptee.swift | 3 +++ .../src/ViewControllers/HomeViewController.m | 7 +++-- Signal/src/call/CallAudioService.swift | 2 ++ Signal/src/call/CallService.swift | 2 ++ Signal/src/call/NonCallKitCallUIAdaptee.swift | 8 +++++- Signal/src/call/OutboundCallInitiator.swift | 2 ++ .../call/Speakerbox/CallKitCallManager.swift | 8 ++++++ .../Speakerbox/CallKitCallUIAdaptee.swift | 2 ++ .../call/UserInterface/CallUIAdapter.swift | 2 ++ .../src/call/WebRTCCallMessageHandler.swift | 4 +++ .../ExperienceUpgradeFinder.swift | 14 ++++++++-- .../environment/PushRegistrationManager.swift | 2 ++ Signal/src/network/GiphyAPI.swift | 6 ++++- Signal/src/network/GiphyDownloader.swift | 2 ++ .../translations/en.lproj/Localizable.strings | 6 ++--- .../contacts/SystemContactsFetcher.swift | 4 +++ .../utils/DeviceSleepManager.swift | 2 ++ SignalMessaging/utils/OWSSwiftUtils.swift | 27 +++++++++++++++++++ 22 files changed, 105 insertions(+), 12 deletions(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 9a7a68517..665fa7048 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -914,7 +914,7 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; [[TSStorageManager sharedManager].newDatabaseConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { - [[ExperienceUpgradeFinder new] markAllAsSeenWithTransaction:transaction]; + [ExperienceUpgradeFinder.sharedManager markAllAsSeenWithTransaction:transaction]; }]; // Start running the disappearing messages job in case the newly registered user // enables this feature diff --git a/Signal/src/Jobs/MessageFetcherJob.swift b/Signal/src/Jobs/MessageFetcherJob.swift index 5ebf8ce84..21a9d1b2a 100644 --- a/Signal/src/Jobs/MessageFetcherJob.swift +++ b/Signal/src/Jobs/MessageFetcherJob.swift @@ -20,6 +20,10 @@ class MessageFetcherJob: NSObject { self.messageReceiver = messageReceiver self.networkManager = networkManager self.signalService = signalService + + super.init() + + SwiftSingletons.register(self) } public func run() -> Promise { diff --git a/Signal/src/Models/AccountManager.swift b/Signal/src/Models/AccountManager.swift index 41c0697a2..191eace3a 100644 --- a/Signal/src/Models/AccountManager.swift +++ b/Signal/src/Models/AccountManager.swift @@ -26,6 +26,10 @@ class AccountManager: NSObject { self.networkManager = textSecureAccountManager.networkManager self.textSecureAccountManager = textSecureAccountManager self.preferences = preferences + + super.init() + + SwiftSingletons.register(self) } // MARK: registration diff --git a/Signal/src/UserInterface/Notifications/CallNotificationsAdapter.swift b/Signal/src/UserInterface/Notifications/CallNotificationsAdapter.swift index 9fa2d9a1e..c61ed4c27 100644 --- a/Signal/src/UserInterface/Notifications/CallNotificationsAdapter.swift +++ b/Signal/src/UserInterface/Notifications/CallNotificationsAdapter.swift @@ -24,6 +24,10 @@ class CallNotificationsAdapter: NSObject { // } else { adaptee = SignalApp.shared().notificationsManager // } + + super.init() + + SwiftSingletons.register(self) } func presentIncomingCall(_ call: SignalCall, callerName: String) { diff --git a/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift b/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift index 7180bbe8f..8ae02ac4a 100644 --- a/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift +++ b/Signal/src/UserInterface/Notifications/UserNotificationsAdaptee.swift @@ -72,8 +72,11 @@ class UserNotificationsAdaptee: NSObject, OWSCallNotificationsAdaptee, UNUserNot override init() { self.center = UNUserNotificationCenter.current() + super.init() + SwiftSingletons.register(self) + center.delegate = self // FIXME TODO only do this after user has registered. diff --git a/Signal/src/ViewControllers/HomeViewController.m b/Signal/src/ViewControllers/HomeViewController.m index 51a2e8390..910f4577f 100644 --- a/Signal/src/ViewControllers/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeViewController.m @@ -56,7 +56,6 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; @property (nonatomic, readonly) AccountManager *accountManager; @property (nonatomic, readonly) OWSContactsManager *contactsManager; -@property (nonatomic, readonly) ExperienceUpgradeFinder *experienceUpgradeFinder; @property (nonatomic, readonly) OWSMessageManager *messagesManager; @property (nonatomic, readonly) OWSMessageSender *messageSender; @property (nonatomic, readonly) OWSBlockingManager *blockingManager; @@ -111,7 +110,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; _blockingManager = [OWSBlockingManager sharedManager]; _blockedPhoneNumberSet = [NSSet setWithArray:[_blockingManager blockedPhoneNumbers]]; - _experienceUpgradeFinder = [ExperienceUpgradeFinder new]; + ExperienceUpgradeFinder.sharedManager; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(blockedPhoneNumbersDidChange:) @@ -530,7 +529,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; __block NSArray *unseenUpgrades; [self.editingDbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - unseenUpgrades = [self.experienceUpgradeFinder allUnseenWithTransaction:transaction]; + unseenUpgrades = [ExperienceUpgradeFinder.sharedManager allUnseenWithTransaction:transaction]; }]; return unseenUpgrades; } @@ -540,7 +539,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; AssertIsOnMainThread(); [self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *_Nonnull transaction) { - [self.experienceUpgradeFinder markAllAsSeenWithTransaction:transaction]; + [ExperienceUpgradeFinder.sharedManager markAllAsSeenWithTransaction:transaction]; }]; } diff --git a/Signal/src/call/CallAudioService.swift b/Signal/src/call/CallAudioService.swift index c739c85dc..574a910f8 100644 --- a/Signal/src/call/CallAudioService.swift +++ b/Signal/src/call/CallAudioService.swift @@ -148,6 +148,8 @@ struct AudioSource: Hashable { super.init() + SwiftSingletons.register(self) + // Configure audio session so we don't prompt user with Record permission until call is connected. audioSession.configure() } diff --git a/Signal/src/call/CallService.swift b/Signal/src/call/CallService.swift index d1b66febd..743eb5d80 100644 --- a/Signal/src/call/CallService.swift +++ b/Signal/src/call/CallService.swift @@ -224,6 +224,8 @@ protocol CallServiceObserver: class { super.init() + SwiftSingletons.register(self) + self.createCallUIAdapter() NotificationCenter.default.addObserver(self, diff --git a/Signal/src/call/NonCallKitCallUIAdaptee.swift b/Signal/src/call/NonCallKitCallUIAdaptee.swift index c20dea878..18b995a4f 100644 --- a/Signal/src/call/NonCallKitCallUIAdaptee.swift +++ b/Signal/src/call/NonCallKitCallUIAdaptee.swift @@ -9,7 +9,7 @@ import SignalMessaging /** * Manage call related UI in a pre-CallKit world. */ -class NonCallKitCallUIAdaptee: CallUIAdaptee { +class NonCallKitCallUIAdaptee: NSObject, CallUIAdaptee { let TAG = "[NonCallKitCallUIAdaptee]" @@ -20,8 +20,14 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee { let hasManualRinger = true required init(callService: CallService, notificationsAdapter: CallNotificationsAdapter) { + AssertIsOnMainThread() + self.callService = callService self.notificationsAdapter = notificationsAdapter + + super.init() + + SwiftSingletons.register(self) } func startOutgoingCall(handle: String) -> SignalCall { diff --git a/Signal/src/call/OutboundCallInitiator.swift b/Signal/src/call/OutboundCallInitiator.swift index 2bca5a7d0..051db267c 100644 --- a/Signal/src/call/OutboundCallInitiator.swift +++ b/Signal/src/call/OutboundCallInitiator.swift @@ -20,6 +20,8 @@ import SignalMessaging self.contactsUpdater = contactsUpdater super.init() + + SwiftSingletons.register(self) } /** diff --git a/Signal/src/call/Speakerbox/CallKitCallManager.swift b/Signal/src/call/Speakerbox/CallKitCallManager.swift index 43422944e..fff993181 100644 --- a/Signal/src/call/Speakerbox/CallKitCallManager.swift +++ b/Signal/src/call/Speakerbox/CallKitCallManager.swift @@ -20,6 +20,14 @@ final class CallKitCallManager: NSObject { let callController = CXCallController() static let kAnonymousCallHandlePrefix = "Signal:" + override required init() { + AssertIsOnMainThread() + + super.init() + + SwiftSingletons.register(self) + } + // MARK: Actions func startCall(_ call: SignalCall) { diff --git a/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift b/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift index 73da4b39f..f44d0af58 100644 --- a/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift +++ b/Signal/src/call/Speakerbox/CallKitCallUIAdaptee.swift @@ -63,6 +63,8 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate { super.init() + SwiftSingletons.register(self) + self.provider.setDelegate(self, queue: nil) } diff --git a/Signal/src/call/UserInterface/CallUIAdapter.swift b/Signal/src/call/UserInterface/CallUIAdapter.swift index 352bc79e1..d7a5f379f 100644 --- a/Signal/src/call/UserInterface/CallUIAdapter.swift +++ b/Signal/src/call/UserInterface/CallUIAdapter.swift @@ -103,6 +103,8 @@ extension CallUIAdaptee { super.init() + SwiftSingletons.register(self) + callService.addObserverAndSyncState(observer: self) } diff --git a/Signal/src/call/WebRTCCallMessageHandler.swift b/Signal/src/call/WebRTCCallMessageHandler.swift index 3f4199a17..162484dfb 100644 --- a/Signal/src/call/WebRTCCallMessageHandler.swift +++ b/Signal/src/call/WebRTCCallMessageHandler.swift @@ -25,6 +25,10 @@ class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { self.accountManager = accountManager self.callService = callService self.messageSender = messageSender + + super.init() + + SwiftSingletons.register(self) } // MARK: - Call Handlers diff --git a/Signal/src/environment/ExperienceUpgrades/ExperienceUpgradeFinder.swift b/Signal/src/environment/ExperienceUpgrades/ExperienceUpgradeFinder.swift index d4bc51390..e4e8588bb 100644 --- a/Signal/src/environment/ExperienceUpgrades/ExperienceUpgradeFinder.swift +++ b/Signal/src/environment/ExperienceUpgrades/ExperienceUpgradeFinder.swift @@ -13,7 +13,17 @@ enum ExperienceUpgradeId: String { } class ExperienceUpgradeFinder: NSObject { - public let TAG = "[ExperienceUpgradeFinder]" + + // MARK - Singleton class + + @objc(sharedManager) + public static let shared = ExperienceUpgradeFinder() + + private override init() { + super.init() + + SwiftSingletons.register(self) + } var videoCalling: ExperienceUpgrade { return ExperienceUpgrade(uniqueId: ExperienceUpgradeId.videoCalling.rawValue, @@ -64,7 +74,7 @@ class ExperienceUpgradeFinder: NSObject { } public func markAllAsSeen(transaction: YapDatabaseReadWriteTransaction) { - Logger.info("\(TAG) marking experience upgrades as seen") + Logger.info("\(logTag) marking experience upgrades as seen") allExperienceUpgrades.forEach { $0.save(with: transaction) } } } diff --git a/Signal/src/environment/PushRegistrationManager.swift b/Signal/src/environment/PushRegistrationManager.swift index cd525d9d7..7a06d4ff1 100644 --- a/Signal/src/environment/PushRegistrationManager.swift +++ b/Signal/src/environment/PushRegistrationManager.swift @@ -31,6 +31,8 @@ public enum PushRegistrationError: Error { private override init() { super.init() + + SwiftSingletons.register(self) } private var userNotificationSettingsPromise: Promise? diff --git a/Signal/src/network/GiphyAPI.swift b/Signal/src/network/GiphyAPI.swift index dbcb09b17..a847ec07b 100644 --- a/Signal/src/network/GiphyAPI.swift +++ b/Signal/src/network/GiphyAPI.swift @@ -271,7 +271,11 @@ extension GiphyError: LocalizedError { static let sharedInstance = GiphyAPI() // Force usage as a singleton - override private init() {} + override private init() { + super.init() + + SwiftSingletons.register(self) + } deinit { NotificationCenter.default.removeObserver(self) diff --git a/Signal/src/network/GiphyDownloader.swift b/Signal/src/network/GiphyDownloader.swift index d4b5e9ba8..47b1949d7 100644 --- a/Signal/src/network/GiphyDownloader.swift +++ b/Signal/src/network/GiphyDownloader.swift @@ -450,6 +450,8 @@ extension URLSessionTask { super.init() + SwiftSingletons.register(self) + ensureGifFolder() } diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index a864628ea..17e20405f 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -428,7 +428,7 @@ "DATABASE_VIEW_OVERLAY_TITLE" = "Updating Database"; /* Message indicating that the debug log is being uploaded. */ -"DEBUG_LOG_ACTIVITY_INDICATOR" = "Sending debug log..."; +"DEBUG_LOG_ACTIVITY_INDICATOR" = "Sending Debug Log..."; /* Message of the debug log alert. */ "DEBUG_LOG_ALERT_MESSAGE" = "What would you like to do with the link to your debug log?"; @@ -449,13 +449,13 @@ "DEBUG_LOG_ALERT_TITLE" = "One More Step"; /* Title of the alert indicating the debug log upload failed. */ -"DEBUG_LOG_FAILURE_ALERT_TITLE" = "Failed to submit debug log"; +"DEBUG_LOG_FAILURE_ALERT_TITLE" = "Failed to Submit Debug Log"; /* Message of the alert before redirecting to Github Issues. */ "DEBUG_LOG_GITHUB_ISSUE_ALERT_MESSAGE" = "The gist link was copied in your clipboard. You are about to be redirected to the GitHub issue list."; /* Title of the alert before redirecting to Github Issues. */ -"DEBUG_LOG_GITHUB_ISSUE_ALERT_TITLE" = "GitHub redirection"; +"DEBUG_LOG_GITHUB_ISSUE_ALERT_TITLE" = "GitHub Redirection"; /* {{Short Date}} when device last communicated with Signal Server. */ "DEVICE_LAST_ACTIVE_AT_LABEL" = "Last active: %@"; diff --git a/SignalMessaging/contacts/SystemContactsFetcher.swift b/SignalMessaging/contacts/SystemContactsFetcher.swift index db9fd1889..5e22e75de 100644 --- a/SignalMessaging/contacts/SystemContactsFetcher.swift +++ b/SignalMessaging/contacts/SystemContactsFetcher.swift @@ -351,6 +351,10 @@ public class SystemContactsFetcher: NSObject { override init() { self.contactStoreAdapter = ContactStoreAdapter() + + super.init() + + SwiftSingletons.register(self) } @objc diff --git a/SignalMessaging/utils/DeviceSleepManager.swift b/SignalMessaging/utils/DeviceSleepManager.swift index feed7d9ec..1cb886c18 100644 --- a/SignalMessaging/utils/DeviceSleepManager.swift +++ b/SignalMessaging/utils/DeviceSleepManager.swift @@ -38,6 +38,8 @@ public class DeviceSleepManager: NSObject { private override init() { super.init() + SwiftSingletons.register(self) + NotificationCenter.default.addObserver(self, selector:#selector(didEnterBackground), name:NSNotification.Name.UIApplicationDidEnterBackground, diff --git a/SignalMessaging/utils/OWSSwiftUtils.swift b/SignalMessaging/utils/OWSSwiftUtils.swift index d70088d68..ce7e3ee77 100644 --- a/SignalMessaging/utils/OWSSwiftUtils.swift +++ b/SignalMessaging/utils/OWSSwiftUtils.swift @@ -20,3 +20,30 @@ public func owsFail(_ message: String) { Logger.flush() assertionFailure(message) } + +public class SwiftSingletons: NSObject { + public static let shared = SwiftSingletons() + + private var classSet = Set() + + private override init() { + super.init() + } + + public func register(_ singleton: AnyObject) { + guard _isDebugAssertConfiguration() else { + return + } + let singletonClassName = String(describing:type(of:singleton)) + guard !classSet.contains(singletonClassName) else { + owsFail("\(self.logTag()) in \(#function) Duplicate singleton: \(singletonClassName).") + return + } + Logger.verbose("\(self.logTag()) in \(#function) Registering singleton: \(singletonClassName).") + classSet.insert(singletonClassName) + } + + public static func register(_ singleton: AnyObject) { + shared.register(singleton) + } +} From 36703d3bbde72f5afc9a8d8f7c7caa73247ea8bc Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 7 Dec 2017 10:35:47 -0500 Subject: [PATCH 2/3] Add asserts around Swift singletons. --- Signal.xcodeproj/project.pbxproj | 4 +++ SignalMessaging/utils/OWSSwiftUtils.swift | 27 ----------------- SignalMessaging/utils/SwiftSingletons.swift | 32 +++++++++++++++++++++ 3 files changed, 36 insertions(+), 27 deletions(-) create mode 100644 SignalMessaging/utils/SwiftSingletons.swift diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index 2e092061d..ab456fc2f 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -106,6 +106,7 @@ 3478506A1FD9B78A007B8332 /* AppSetup.h in Headers */ = {isa = PBXBuildFile; fileRef = 347850661FD9B789007B8332 /* AppSetup.h */; settings = {ATTRIBUTES = (Public, ); }; }; 3478506B1FD9B78A007B8332 /* NoopCallMessageHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347850671FD9B78A007B8332 /* NoopCallMessageHandler.swift */; }; 3478506C1FD9B78A007B8332 /* NoopNotificationsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347850681FD9B78A007B8332 /* NoopNotificationsManager.swift */; }; + 347850591FD9972E007B8332 /* SwiftSingletons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 347850581FD9972E007B8332 /* SwiftSingletons.swift */; }; 3497DBEC1ECE257500DB2605 /* OWSCountryMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = 3497DBEB1ECE257500DB2605 /* OWSCountryMetadata.m */; }; 3497DBEF1ECE2E4700DB2605 /* DomainFrontingCountryViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3497DBEE1ECE2E4700DB2605 /* DomainFrontingCountryViewController.m */; }; 34B0796D1FCF46B100E248C2 /* MainAppContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 34B0796B1FCF46B000E248C2 /* MainAppContext.m */; }; @@ -572,6 +573,7 @@ 347850661FD9B789007B8332 /* AppSetup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppSetup.h; sourceTree = ""; }; 347850671FD9B78A007B8332 /* NoopCallMessageHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoopCallMessageHandler.swift; sourceTree = ""; }; 347850681FD9B78A007B8332 /* NoopNotificationsManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NoopNotificationsManager.swift; sourceTree = ""; }; + 347850581FD9972E007B8332 /* SwiftSingletons.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftSingletons.swift; sourceTree = ""; }; 348F2EAD1F0D21BC00D4ECE0 /* DeviceSleepManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceSleepManager.swift; sourceTree = ""; }; 3495BC911F1426B800B478F5 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = translations/ar.lproj/Localizable.strings; sourceTree = ""; }; 3497DBEA1ECE257500DB2605 /* OWSCountryMetadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSCountryMetadata.h; sourceTree = ""; }; @@ -1097,6 +1099,7 @@ 346129BE1FD2068600532771 /* ThreadUtil.m */, B97940251832BD2400BD66CB /* UIUtil.h */, B97940261832BD2400BD66CB /* UIUtil.m */, + 347850581FD9972E007B8332 /* SwiftSingletons.swift */, 346129751FD1E0B500532771 /* WeakTimer.swift */, ); path = utils; @@ -2685,6 +2688,7 @@ 346129E61FD5C0C600532771 /* OWSDatabaseMigrationRunner.m in Sources */, 346129AB1FD1F0EE00532771 /* OWSFormat.m in Sources */, 451F8A461FD715BA005CB9DA /* OWSGroupAvatarBuilder.m in Sources */, + 347850591FD9972E007B8332 /* SwiftSingletons.swift in Sources */, 346129961FD1E30000532771 /* OWSDatabaseMigration.m in Sources */, 346129CD1FD2072E00532771 /* UIImage+OWS.m in Sources */, 450998661FD8BD9C00D89EB3 /* FullImageViewController.m in Sources */, diff --git a/SignalMessaging/utils/OWSSwiftUtils.swift b/SignalMessaging/utils/OWSSwiftUtils.swift index ce7e3ee77..d70088d68 100644 --- a/SignalMessaging/utils/OWSSwiftUtils.swift +++ b/SignalMessaging/utils/OWSSwiftUtils.swift @@ -20,30 +20,3 @@ public func owsFail(_ message: String) { Logger.flush() assertionFailure(message) } - -public class SwiftSingletons: NSObject { - public static let shared = SwiftSingletons() - - private var classSet = Set() - - private override init() { - super.init() - } - - public func register(_ singleton: AnyObject) { - guard _isDebugAssertConfiguration() else { - return - } - let singletonClassName = String(describing:type(of:singleton)) - guard !classSet.contains(singletonClassName) else { - owsFail("\(self.logTag()) in \(#function) Duplicate singleton: \(singletonClassName).") - return - } - Logger.verbose("\(self.logTag()) in \(#function) Registering singleton: \(singletonClassName).") - classSet.insert(singletonClassName) - } - - public static func register(_ singleton: AnyObject) { - shared.register(singleton) - } -} diff --git a/SignalMessaging/utils/SwiftSingletons.swift b/SignalMessaging/utils/SwiftSingletons.swift new file mode 100644 index 000000000..b69231b7b --- /dev/null +++ b/SignalMessaging/utils/SwiftSingletons.swift @@ -0,0 +1,32 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +import Foundation + +public class SwiftSingletons: NSObject { + public static let shared = SwiftSingletons() + + private var classSet = Set() + + private override init() { + super.init() + } + + public func register(_ singleton: AnyObject) { + guard _isDebugAssertConfiguration() else { + return + } + let singletonClassName = String(describing:type(of:singleton)) + guard !classSet.contains(singletonClassName) else { + owsFail("\(self.logTag()) in \(#function) Duplicate singleton: \(singletonClassName).") + return + } + Logger.verbose("\(self.logTag()) in \(#function) Registering singleton: \(singletonClassName).") + classSet.insert(singletonClassName) + } + + public static func register(_ singleton: AnyObject) { + shared.register(singleton) + } +} From b12f192c6f3d0f355257fec108520ec46677a198 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Thu, 7 Dec 2017 14:31:00 -0500 Subject: [PATCH 3/3] Respond to CR. --- Signal/src/ViewControllers/HomeViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Signal/src/ViewControllers/HomeViewController.m b/Signal/src/ViewControllers/HomeViewController.m index 910f4577f..050cd1a65 100644 --- a/Signal/src/ViewControllers/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeViewController.m @@ -110,6 +110,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; _blockingManager = [OWSBlockingManager sharedManager]; _blockedPhoneNumberSet = [NSSet setWithArray:[_blockingManager blockedPhoneNumbers]]; + // Ensure ExperienceUpgradeFinder has been initialized. ExperienceUpgradeFinder.sharedManager; [[NSNotificationCenter defaultCenter] addObserver:self