Skip to content
Snippets Groups Projects
Commit 59f7ea31 authored by Romain Bertozzi's avatar Romain Bertozzi Committed by Silbino Gonçalves Matado
Browse files

arch: remove singleton and add DI


This patch removes the singleton of the AccountService and
AccountAdapter.

These elements are still instantiated and kept once in the application
thanks to the AppDelegate.
They are then injected by initializers to the rest of the app.

In order to achieve this, we had to change the delegate connection
between the AccountAdapter and its Service. Indeed, we do not have a
singleton pattern anymore and we can not keep a "self" reference
because of the exportable_callback behaviour.
So, we set the delegate to a static delegate.

Tuleap: #1391
Change-Id: I56d6e79f7d3c09d6ac3166643fa293cf6df67555
Reviewed-by: default avatarSilbino Gonçalves Matado <silbino.gmatado@savoirfairelinux.com>
parent 3d98ef99
No related branches found
No related tags found
No related merge requests found
...@@ -43,18 +43,26 @@ class CreateRingAccountViewModel { ...@@ -43,18 +43,26 @@ class CreateRingAccountViewModel {
*/ */
fileprivate var account: AccountModel? fileprivate var account: AccountModel?
/**
The accountService instance injected in initializer.
*/
fileprivate let accountService: AccountsService
/** /**
Default constructor Default constructor
*/ */
init() { init(withAccountService accountService: AccountsService) {
self.account = nil self.account = nil
self.accountService = accountService
} }
/** /**
Constructor with AccountModel. Constructor with AccountModel.
*/ */
init(withAccountModel account: AccountModel?) { init(withAccountService accountService: AccountsService,
accountModel account: AccountModel?) {
self.account = account self.account = account
self.accountService = accountService
} }
/** /**
...@@ -81,7 +89,7 @@ class CreateRingAccountViewModel { ...@@ -81,7 +89,7 @@ class CreateRingAccountViewModel {
//~ simultaneously authorized. //~ simultaneously authorized.
self?.addAccountDisposable?.dispose() self?.addAccountDisposable?.dispose()
//~ Subscribe on the AccountsService responseStream to get results. //~ Subscribe on the AccountsService responseStream to get results.
self?.addAccountDisposable = AccountsService.sharedInstance self?.addAccountDisposable = self?.accountService
.sharedResponseStream .sharedResponseStream
.subscribe(onNext:{ (event) in .subscribe(onNext:{ (event) in
if event.eventType == ServiceEventType.AccountsChanged { if event.eventType == ServiceEventType.AccountsChanged {
...@@ -93,7 +101,7 @@ class CreateRingAccountViewModel { ...@@ -93,7 +101,7 @@ class CreateRingAccountViewModel {
self?.addAccountDisposable?.addDisposableTo((self?.disposeBag)!) self?.addAccountDisposable?.addDisposableTo((self?.disposeBag)!)
//~ Launch the action. //~ Launch the action.
AccountsService.sharedInstance.addAccount() self?.accountService.addAccount()
}, },
onError: { (error) in onError: { (error) in
onErrorCallback?(error) onErrorCallback?(error)
......
...@@ -26,7 +26,8 @@ import CoreData ...@@ -26,7 +26,8 @@ import CoreData
class AppDelegate: UIResponder, UIApplicationDelegate { class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? var window: UIWindow?
let daemonService = DaemonService(dRingAdaptor: DRingAdapter()) static let daemonService = DaemonService(dRingAdaptor: DRingAdapter())
static let accountService = AccountsService(withAccountAdapter: AccountAdapter())
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
SystemAdapter().registerConfigurationHandler() SystemAdapter().registerConfigurationHandler()
...@@ -123,7 +124,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -123,7 +124,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: - Ring Daemon // MARK: - Ring Daemon
fileprivate func startDaemon() { fileprivate func startDaemon() {
do { do {
try self.daemonService.startDaemon() try AppDelegate.daemonService.startDaemon()
} catch StartDaemonError.InitializationFailure { } catch StartDaemonError.InitializationFailure {
print("Daemon failed to initialize.") print("Daemon failed to initialize.")
} catch StartDaemonError.StartFailure { } catch StartDaemonError.StartFailure {
...@@ -137,7 +138,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ...@@ -137,7 +138,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
fileprivate func stopDaemon() { fileprivate func stopDaemon() {
do { do {
try self.daemonService.stopDaemon() try AppDelegate.daemonService.stopDaemon()
} catch StopDaemonError.DaemonNotRunning { } catch StopDaemonError.DaemonNotRunning {
print("Daemon failed to stop because it was not already running.") print("Daemon failed to stop because it was not already running.")
} catch { } catch {
......
...@@ -41,9 +41,7 @@ ...@@ -41,9 +41,7 @@
/** /**
Delegate where all the accounts events will be forwarded. Delegate where all the accounts events will be forwarded.
*/ */
@property (nonatomic, weak) id <AccountAdapterDelegate> delegate; @property (class, nonatomic, weak) id <AccountAdapterDelegate> delegate;
+ (instancetype)sharedManager;
- (NSDictionary *)getAccountDetails:(NSString *)accountID; - (NSDictionary *)getAccountDetails:(NSString *)accountID;
......
...@@ -30,16 +30,10 @@ ...@@ -30,16 +30,10 @@
using namespace DRing; using namespace DRing;
#pragma mark Singleton Methods /// Static delegate that will receive the propagated daemon events
+ (instancetype)sharedManager { static id <AccountAdapterDelegate> _delegate;
static AccountAdapter* sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
#pragma mark Init
- (id)init { - (id)init {
if (self = [super init]) { if (self = [super init]) {
[self registerConfigurationHandler]; [self registerConfigurationHandler];
...@@ -53,8 +47,8 @@ using namespace DRing; ...@@ -53,8 +47,8 @@ using namespace DRing;
std::map<std::string, std::shared_ptr<CallbackWrapperBase>> confHandlers; std::map<std::string, std::shared_ptr<CallbackWrapperBase>> confHandlers;
confHandlers.insert(exportable_callback<ConfigurationSignal::AccountsChanged>([&]() { confHandlers.insert(exportable_callback<ConfigurationSignal::AccountsChanged>([&]() {
//~ Using sharedManager to avoid as possible to retain self in the block. //~ Using sharedManager to avoid as possible to retain self in the block.
if ([[AccountAdapter sharedManager] delegate]) { if (AccountAdapter.delegate) {
[[[AccountAdapter sharedManager] delegate] accountsChanged]; [AccountAdapter.delegate accountsChanged];
} }
})); }));
registerConfHandlers(confHandlers); registerConfHandlers(confHandlers);
...@@ -102,4 +96,14 @@ using namespace DRing; ...@@ -102,4 +96,14 @@ using namespace DRing;
} }
#pragma mark - #pragma mark -
#pragma mark AccountAdapterDelegate
+ (id <AccountAdapterDelegate>)delegate {
return _delegate;
}
+ (void) setDelegate:(id<AccountAdapterDelegate>)delegate {
_delegate = delegate;
}
#pragma mark -
@end @end
...@@ -21,9 +21,11 @@ ...@@ -21,9 +21,11 @@
import UIKit import UIKit
class MainTabBarViewController: UITabBarController { class MainTabBarViewController: UITabBarController {
fileprivate let accountService = AppDelegate.accountService
override func viewDidAppear(_ animated: Bool) { override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) super.viewDidAppear(animated)
if !AccountsService.sharedInstance.hasAccounts() { if !accountService.hasAccounts() {
self.presentWalkthrough() self.presentWalkthrough()
} }
} }
......
...@@ -23,7 +23,7 @@ import UIKit ...@@ -23,7 +23,7 @@ import UIKit
class MeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { class MeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// MARK: - Properties // MARK: - Properties
let accountService = AccountsService.sharedInstance let accountService = AppDelegate.accountService
@IBOutlet weak var accountTableView: UITableView! @IBOutlet weak var accountTableView: UITableView!
@IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var qrImageView: UIImageView! @IBOutlet weak var qrImageView: UIImageView!
......
...@@ -25,10 +25,9 @@ import RxSwift ...@@ -25,10 +25,9 @@ import RxSwift
class AccountsService: AccountAdapterDelegate { class AccountsService: AccountAdapterDelegate {
// MARK: Private members // MARK: Private members
/** /**
AccountConfigurationManagerAdaptator instance. Used to register the service to daemon events, injected by constructor.
Used to register the service to daemon events.
*/ */
fileprivate let confAdapter = AccountAdapter.sharedManager() as AccountAdapter fileprivate let accountAdapter: AccountAdapter
/** /**
Fileprivate Accounts list. Fileprivate Accounts list.
...@@ -74,10 +73,7 @@ class AccountsService: AccountAdapterDelegate { ...@@ -74,10 +73,7 @@ class AccountsService: AccountAdapterDelegate {
*/ */
var sharedResponseStream: Observable<ServiceEvent> var sharedResponseStream: Observable<ServiceEvent>
// MARK: - Singleton init(withAccountAdapter accountAdapter: AccountAdapter) {
static let sharedInstance = AccountsService()
fileprivate init() {
self.accountList = [] self.accountList = []
self.responseStream.addDisposableTo(disposeBag) self.responseStream.addDisposableTo(disposeBag)
...@@ -85,9 +81,10 @@ class AccountsService: AccountAdapterDelegate { ...@@ -85,9 +81,10 @@ class AccountsService: AccountAdapterDelegate {
//~ Create a shared stream based on the responseStream one. //~ Create a shared stream based on the responseStream one.
self.sharedResponseStream = responseStream.share() self.sharedResponseStream = responseStream.share()
//~ Registering to the AccountConfigurationManagerAdaptator with self as delegate in order self.accountAdapter = accountAdapter
//~ to receive delegation callbacks. //~ Registering to the accountAdatpter with self as delegate in order to receive delegation
self.confAdapter.delegate = self //~ callbacks.
AccountAdapter.delegate = self
} }
// MARK: - Methods // MARK: - Methods
...@@ -105,7 +102,7 @@ class AccountsService: AccountAdapterDelegate { ...@@ -105,7 +102,7 @@ class AccountsService: AccountAdapterDelegate {
func addAccount() { func addAccount() {
// TODO: This need work for all account type // TODO: This need work for all account type
let details:NSMutableDictionary? = confAdapter.getAccountTemplate("RING") let details:NSMutableDictionary? = self.accountAdapter.getAccountTemplate("RING")
if details == nil { if details == nil {
print("Error retrieving Ring account template, can not continue"); print("Error retrieving Ring account template, can not continue");
return; return;
...@@ -113,13 +110,13 @@ class AccountsService: AccountAdapterDelegate { ...@@ -113,13 +110,13 @@ class AccountsService: AccountAdapterDelegate {
details!.setValue("iOS", forKey: "Account.alias") details!.setValue("iOS", forKey: "Account.alias")
details!.setValue("iOS", forKey: "Account.displayName") details!.setValue("iOS", forKey: "Account.displayName")
let convertedDetails = details as NSDictionary? as? [AnyHashable: Any] ?? [:] let convertedDetails = details as NSDictionary? as? [AnyHashable: Any] ?? [:]
let addResult:String! = confAdapter.addAccount(convertedDetails) let addResult:String! = self.accountAdapter.addAccount(convertedDetails)
print(addResult); print(addResult);
} }
func removeAccount(_ row: Int) { func removeAccount(_ row: Int) {
if row < accountList.count { if row < accountList.count {
confAdapter.removeAccount(accountList[row].id) self.accountAdapter.removeAccount(accountList[row].id)
} }
} }
......
...@@ -25,7 +25,7 @@ import RxSwift ...@@ -25,7 +25,7 @@ import RxSwift
class CreateRingAccountViewController: UIViewController { class CreateRingAccountViewController: UIViewController {
var mAccountViewModel = CreateRingAccountViewModel() var mAccountViewModel = CreateRingAccountViewModel(withAccountService: AppDelegate.accountService)
@IBOutlet weak var mCreateAccountButton: RoundedButton! @IBOutlet weak var mCreateAccountButton: RoundedButton!
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment