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