Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] DI containerの設定 #138

Open
wants to merge 3 commits into
base: new-architecture
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions SyncPod.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
0D7FC6A020B172A400CB4169 /* ApplicationCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7FC69F20B172A400CB4169 /* ApplicationCoordinator.swift */; };
0D7FC6A320B1949D00CB4169 /* WelcomeCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7FC6A220B1949D00CB4169 /* WelcomeCoordinator.swift */; };
0D7FC6A520B1966300CB4169 /* BaseCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7FC6A420B1966300CB4169 /* BaseCoordinator.swift */; };
0D7FC6AA20B1C18200CB4169 /* ViewControllerAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7FC6A920B1C18200CB4169 /* ViewControllerAssembly.swift */; };
0D7FC6AC20B1C35B00CB4169 /* ViewModelAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7FC6AB20B1C35B00CB4169 /* ViewModelAssembly.swift */; };
0D7FC6B020B1C6F300CB4169 /* CoordinatorAssembly.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7FC6AF20B1C6F300CB4169 /* CoordinatorAssembly.swift */; };
0D7FC6B220B1C9DF00CB4169 /* DependencyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D7FC6B120B1C9DF00CB4169 /* DependencyManager.swift */; };
0D8BB2B62010A25700C7F6A9 /* ActionCableClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D8BB2B52010A25700C7F6A9 /* ActionCableClient.framework */; };
0D8BB2B82010A37900C7F6A9 /* Starscream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0D8BB2B72010A37900C7F6A9 /* Starscream.framework */; };
0DE94BFD201289A700E26582 /* YouTubePlayer.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0DE94BFC201289A700E26582 /* YouTubePlayer.framework */; };
Expand Down Expand Up @@ -73,6 +77,10 @@
0D7FC69F20B172A400CB4169 /* ApplicationCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationCoordinator.swift; sourceTree = "<group>"; };
0D7FC6A220B1949D00CB4169 /* WelcomeCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeCoordinator.swift; sourceTree = "<group>"; };
0D7FC6A420B1966300CB4169 /* BaseCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseCoordinator.swift; sourceTree = "<group>"; };
0D7FC6A920B1C18200CB4169 /* ViewControllerAssembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewControllerAssembly.swift; sourceTree = "<group>"; };
0D7FC6AB20B1C35B00CB4169 /* ViewModelAssembly.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModelAssembly.swift; sourceTree = "<group>"; };
0D7FC6AF20B1C6F300CB4169 /* CoordinatorAssembly.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoordinatorAssembly.swift; sourceTree = "<group>"; };
0D7FC6B120B1C9DF00CB4169 /* DependencyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DependencyManager.swift; sourceTree = "<group>"; };
0D8BB2B52010A25700C7F6A9 /* ActionCableClient.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ActionCableClient.framework; path = Carthage/Build/iOS/ActionCableClient.framework; sourceTree = "<group>"; };
0D8BB2B72010A37900C7F6A9 /* Starscream.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Starscream.framework; path = Carthage/Build/iOS/Starscream.framework; sourceTree = "<group>"; };
0DE94BFA2012899600E26582 /* YouTubePlayer.framework.dSYM */ = {isa = PBXFileReference; lastKnownFileType = wrapper.dsym; name = YouTubePlayer.framework.dSYM; path = Carthage/Build/iOS/YouTubePlayer.framework.dSYM; sourceTree = "<group>"; };
Expand All @@ -92,7 +100,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
0D86F07520B2AA8E00FA68C7 /* SwinjectStoryboard.framework in Frameworks */,
0D7FC6B420B1DDA100CB4169 /* SwinjectStoryboard.framework in Frameworks */,
0DFF805820B157550087411D /* RxCocoa.framework in Frameworks */,
0DF11A0220A46E5C00D04895 /* Swinject.framework in Frameworks */,
0DF11A0020A46DDB00D04895 /* RxAlamofire.framework in Frameworks */,
Expand Down Expand Up @@ -128,7 +136,7 @@
0D4B438220099E540035DF1D /* Frameworks */ = {
isa = PBXGroup;
children = (
0D86F07420B2AA8E00FA68C7 /* SwinjectStoryboard.framework */,
0D7FC6B320B1DDA100CB4169 /* SwinjectStoryboard.framework */,
0DFF805720B157550087411D /* RxCocoa.framework */,
0DFF805520B1573F0087411D /* RxCocoa.framework.dSYM */,
0DF11A0120A46E5C00D04895 /* Swinject.framework */,
Expand Down Expand Up @@ -171,6 +179,7 @@
0D5B826E1FC9A5D30055A72C /* SyncPod */ = {
isa = PBXGroup;
children = (
0D7FC6A620B1BD9200CB4169 /* di */,
0D7FC6A120B1945400CB4169 /* coordinator */,
0D7FC69B20B164BF00CB4169 /* viewmodel */,
0DFF805320B155CB0087411D /* view */,
Expand Down Expand Up @@ -219,6 +228,17 @@
path = coordinator;
sourceTree = "<group>";
};
0D7FC6A620B1BD9200CB4169 /* di */ = {
isa = PBXGroup;
children = (
0D7FC6A920B1C18200CB4169 /* ViewControllerAssembly.swift */,
0D7FC6AB20B1C35B00CB4169 /* ViewModelAssembly.swift */,
0D7FC6AF20B1C6F300CB4169 /* CoordinatorAssembly.swift */,
0D7FC6B120B1C9DF00CB4169 /* DependencyManager.swift */,
);
path = di;
sourceTree = "<group>";
};
0DFF805020B155890087411D /* storyboard */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -411,9 +431,13 @@
files = (
0D5B82701FC9A5D30055A72C /* AppDelegate.swift in Sources */,
0D7FC6A520B1966300CB4169 /* BaseCoordinator.swift in Sources */,
0D7FC6B220B1C9DF00CB4169 /* DependencyManager.swift in Sources */,
0D7FC6B020B1C6F300CB4169 /* CoordinatorAssembly.swift in Sources */,
0D7FC6AC20B1C35B00CB4169 /* ViewModelAssembly.swift in Sources */,
0D7FC69D20B164D100CB4169 /* WelcomeViewModel.swift in Sources */,
0D7FC6A320B1949D00CB4169 /* WelcomeCoordinator.swift in Sources */,
0D7FC69A20B1636700CB4169 /* WelcomeViewController.swift in Sources */,
0D7FC6AA20B1C18200CB4169 /* ViewControllerAssembly.swift in Sources */,
0D7FC6A020B172A400CB4169 /* ApplicationCoordinator.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
11 changes: 7 additions & 4 deletions SyncPod/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,29 @@
//

import UIKit
import Swinject
import SwinjectStoryboard

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?
lazy var applicationCoordinator = ApplicationCoordinator(window: self.window!)
lazy var coordinator = DependencyManager.getResolver().resolve(ApplicationCoordinator.self)!
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CoordinatorをDIするメリットがあまり思いつかなかったんだが,どういったメリットが有るんだろうか.


func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?
) -> Bool {
applicationCoordinator.start()
coordinator.start()
return true
}

func application(
_ application: UIApplication, open url: URL,
_ application: UIApplication,
open url: URL,
options: [UIApplicationOpenURLOptionsKey: Any] = [:]
) -> Bool {
applicationCoordinator.start()
coordinator.start()
return true
}

Expand Down
6 changes: 2 additions & 4 deletions SyncPod/coordinator/ApplicationCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@
import UIKit

class ApplicationCoordinator: BaseCoordinator {
private let window: UIWindow
private let welcomeCoordinator: WelcomeCoordinator

init(window: UIWindow) {
self.window = window
self.welcomeCoordinator = WelcomeCoordinator(window: window)
init(welcomeCoordinator: WelcomeCoordinator) {
self.welcomeCoordinator = welcomeCoordinator
}

func start() {
Expand Down
15 changes: 6 additions & 9 deletions SyncPod/coordinator/WelcomeCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,18 @@
//

import UIKit
import SwinjectStoryboard

class WelcomeCoordinator: BaseCoordinator {
weak var delegate = UIApplication.shared.delegate as? AppDelegate
private let window: UIWindow
private let storyboard: UIStoryboard
private let storyboard: SwinjectStoryboard
private var nowViewController: UIViewController

init(window: UIWindow) {
self.window = window
self.storyboard = UIStoryboard(name: "Welcome", bundle: nil)
init() {
self.window = (delegate?.window)!
self.storyboard = SwinjectStoryboard.create(name: "Welcome", bundle: nil)
self.nowViewController = storyboard.instantiateViewController(withIdentifier: "WelcomeView")
if let welcomeVC = nowViewController as? WelcomeViewConstoller {
let viewModel = WelcomeViewModel()
viewModel.coordinator = self
welcomeVC.viewModel = viewModel
}
}

func start() {
Expand Down
24 changes: 24 additions & 0 deletions SyncPod/di/CoordinatorAssembly.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// CoordinatorAssembly.swift
// SyncPod
//
// Created by 森篤史 on 2018/05/20.
// Copyright © 2018年 Cyder. All rights reserved.
//

import UIKit
import Swinject

class CoordinatorAssembly: Assembly {
func assemble(container: Container) {
container.register(ApplicationCoordinator.self) { res in
ApplicationCoordinator(
welcomeCoordinator: res.resolve(WelcomeCoordinator.self)!
)
}.inObjectScope(.container)

container.register(WelcomeCoordinator.self) { _ in
WelcomeCoordinator()
}.inObjectScope(.container)
}
}
22 changes: 22 additions & 0 deletions SyncPod/di/DependencyManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// DependencyManager.swift
// SyncPod
//
// Created by 森篤史 on 2018/05/21.
// Copyright © 2018年 Cyder. All rights reserved.
//

import Swinject
import SwinjectStoryboard

class DependencyManager {
static let assembler = Assembler([
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

カプセル化を試みているなら,ここはprivateの方がいいかもしれないです.
また,この使用方法ならclassじゃなくてenumでも良いかも.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

また,この実装だとどこからでもDI出来てしまうが,それが実装意図に沿っているかも併せて気になりました.

CoordinatorAssembly(),
ViewModelAssembly(),
ViewControllerAssembly()
], container: SwinjectStoryboard.defaultContainer)

static func getResolver() -> Resolver {
return assembler.resolver
}
}
18 changes: 18 additions & 0 deletions SyncPod/di/ViewControllerAssembly.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// ViewControllerAssembly.swift
// SyncPod
//
// Created by 森篤史 on 2018/05/20.
// Copyright © 2018年 Cyder. All rights reserved.
//

import Swinject
import SwinjectStoryboard

class ViewControllerAssembly: Assembly {
func assemble(container: Container) {
container.storyboardInitCompleted(WelcomeViewConstoller.self) { res, viewController in
viewController.viewModel = res.resolve(WelcomeViewModel.self)!
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

抽象に依存してないが,これは実装意図に沿っているだろうか.
また,ここでランタイムエラーが起きないかも併せて気になりました.

}
}
}
19 changes: 19 additions & 0 deletions SyncPod/di/ViewModelAssembly.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// ViewModelAssembly.swift
// SyncPod
//
// Created by 森篤史 on 2018/05/20.
// Copyright © 2018年 Cyder. All rights reserved.
//

import Swinject

class ViewModelAssembly: Assembly {
func assemble(container: Container) {
container.register(WelcomeViewModel.self) { res in
WelcomeViewModel(
coordinator: res.resolve(WelcomeCoordinator.self)!
)
}.inObjectScope(.container)
}
}
8 changes: 5 additions & 3 deletions SyncPod/view/viewcontroller/WelcomeViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,25 @@ import RxCocoa

class WelcomeViewConstoller: UIViewController {
let disposeBag = DisposeBag()
var viewModel: WelcomeViewModel?
var viewModel: WelcomeViewModel!

@IBOutlet weak var signInButton: UIBarButtonItem!
@IBOutlet weak var signUpButton: UIBarButtonItem!

override func viewDidLoad() {
super.viewDidLoad()

print(viewModel)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

デバッグ時に使用していた記述が残っています.


setUpDataBinding()
}

private func setUpDataBinding() {
signInButton.rx.tap
.subscribe({ _ in self.viewModel?.onSignInClicked() })
.subscribe({ _ in self.viewModel.onSignInClicked() })
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

循環参照を起こします.
下記のように変更することを推奨します.

.subscribe({ [weak self] _ in self?.viewModel.onSignInClicked() })

.disposed(by: disposeBag)
signUpButton.rx.tap
.subscribe({ _ in self.viewModel?.onSignUpClicked() })
.subscribe({ _ in self.viewModel.onSignUpClicked() })
.disposed(by: disposeBag)
}
}
9 changes: 6 additions & 3 deletions SyncPod/viewmodel/WelcomeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
import Foundation

class WelcomeViewModel {
var coordinator: WelcomeCoordinator?
let coordinator: WelcomeCoordinator
Copy link

@k-kohey k-kohey Mar 17, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CoordinatorがWelcomeViewControllerへの参照を持っていれば,循環参照が起きてそうだと思ったんだが,どうだろうか.
coordinatorはaqppDelegateに保持されているので,解放されることは無さそう.なので

private unowned let coordinator: WelcomeCoordinator

が良さそう.

一方で,ViewModelがCoordinatorを直接持つ必要も無さそうなので,外部から遷移ロジックを注入するのが一番安全かも.


init(coordinator: WelcomeCoordinator) {
self.coordinator = coordinator
}
func onSignInClicked() {
coordinator?.navigateToSignIn()
coordinator.navigateToSignIn()
}

func onSignUpClicked() {
coordinator?.navigateToSignUp()
coordinator.navigateToSignUp()
}
}