-
Notifications
You must be signed in to change notification settings - Fork 143
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
Ability to pass arguments #62
base: master
Are you sure you want to change the base?
Changes from all commits
1833160
2008562
e182cbe
6c8dddd
fa8cd96
ab28482
f582e1b
7cfd87e
f9267d2
ffd6330
a17f7ba
679e157
8543be2
39040e8
c144701
cac17fb
33f45f1
14ae7ec
d9d4628
27dc846
3884665
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,3 @@ | ||
github "Swinject/Swinject" ~> 2.4 | ||
github "Quick/Nimble" | ||
github "Quick/Quick" |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -93,7 +93,7 @@ public class SwinjectStoryboard: _SwinjectStoryboardBase, SwinjectStoryboardProt | |
return viewController | ||
} | ||
|
||
private func injectDependency(to viewController: UIViewController) { | ||
fileprivate func injectDependency(to viewController: UIViewController) { | ||
guard !viewController.wasInjected else { return } | ||
defer { viewController.wasInjected = true } | ||
|
||
|
@@ -105,6 +105,7 @@ public class SwinjectStoryboard: _SwinjectStoryboardBase, SwinjectStoryboardProt | |
if let container = container.value as? _Resolver { | ||
let option = SwinjectStoryboardOption(controllerType: type(of: viewController)) | ||
typealias FactoryType = ((Resolver, Container.Controller)) -> Any | ||
|
||
let _ = container._resolve(name: registrationName, option: option) { (factory: FactoryType) in factory((self.container.value, viewController)) as Any } as Container.Controller? | ||
} else { | ||
fatalError("A type conforming Resolver protocol must conform _Resolver protocol too.") | ||
|
@@ -210,3 +211,100 @@ public class SwinjectStoryboard: _SwinjectStoryboardBase, SwinjectStoryboardProt | |
} | ||
|
||
#endif | ||
|
||
|
||
extension SwinjectStoryboard { | ||
|
||
#if os(iOS) || os(tvOS) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We probably want to extend this for |
||
|
||
private func injectDependency<Arg>(to viewController: UIViewController, arg: Arg) { | ||
guard !viewController.wasInjected else { return } | ||
defer { viewController.wasInjected = true } | ||
|
||
let registrationName = viewController.swinjectRegistrationName | ||
|
||
if let container = container.value as? _Resolver { | ||
let option = SwinjectStoryboardOption(controllerType: type(of: viewController)) | ||
typealias FactoryType = ((Resolver, Container.Controller, Arg)) -> Any | ||
let _ = container._resolve(name: registrationName, option: option) { (factory: FactoryType) in factory((self.container.value, viewController, arg)) as Any } as Container.Controller? | ||
} else { | ||
fatalError("A type conforming Resolver protocol must conform _Resolver protocol too.") | ||
} | ||
|
||
for child in viewController.children { | ||
injectDependency(to: child) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a lot of repeated code between methods with different arguments. Can we reuse this code somehow? Alternatively we can generate this similarly to how it is done in Swinject (see. Container.Arguments.erb) |
||
|
||
private func injectDependency<Arg1, Arg2>(to viewController: UIViewController, arg1: Arg1, arg2: Arg2) { | ||
guard !viewController.wasInjected else { return } | ||
defer { viewController.wasInjected = true } | ||
|
||
let registrationName = viewController.swinjectRegistrationName | ||
|
||
if let container = container.value as? _Resolver { | ||
let option = SwinjectStoryboardOption(controllerType: type(of: viewController)) | ||
typealias FactoryType = ((Resolver, Container.Controller, Arg1, Arg2)) -> Any | ||
let _ = container._resolve(name: registrationName, option: option) { (factory: FactoryType) in factory((self.container.value, viewController, arg1, arg2)) as Any } as Container.Controller? | ||
} else { | ||
fatalError("A type conforming Resolver protocol must conform _Resolver protocol too.") | ||
} | ||
|
||
for child in viewController.children { | ||
injectDependency(to: child) | ||
} | ||
} | ||
|
||
private func injectDependency<Arg1, Arg2, Arg3>(to viewController: UIViewController, | ||
arg1: Arg1, arg2: Arg2, arg3: Arg3) { | ||
guard !viewController.wasInjected else { return } | ||
defer { viewController.wasInjected = true } | ||
|
||
let registrationName = viewController.swinjectRegistrationName | ||
|
||
if let container = container.value as? _Resolver { | ||
let option = SwinjectStoryboardOption(controllerType: type(of: viewController)) | ||
typealias FactoryType = ((Resolver, Container.Controller, Arg1, Arg2, Arg3)) -> Any | ||
let _ = container._resolve(name: registrationName, option: option) { (factory: FactoryType) in factory((self.container.value, viewController, arg1, arg2, arg3)) as Any } as Container.Controller? | ||
} else { | ||
fatalError("A type conforming Resolver protocol must conform _Resolver protocol too.") | ||
} | ||
|
||
for child in viewController.children { | ||
injectDependency(to: child) | ||
} | ||
} | ||
|
||
//MARK: - instantiateViewController with Args | ||
|
||
public func instantiateViewController<Arg>(withIdentifier identifier: String, | ||
arg: Arg) -> UIViewController { | ||
let viewController = loadViewController(with: identifier) | ||
injectDependency(to: viewController, arg: arg) | ||
return viewController | ||
} | ||
|
||
public func instantiateViewController<Arg1, Arg2>(withIdentifier identifier: String, | ||
arg1: Arg1, arg2: Arg2) -> UIViewController { | ||
let viewController = loadViewController(with: identifier) | ||
injectDependency(to: viewController, arg1: arg1, arg2: arg2) | ||
return viewController | ||
} | ||
|
||
public func instantiateViewController<Arg1, Arg2, Arg3>(withIdentifier identifier: String, | ||
arg1: Arg1, arg2: Arg2, arg3: Arg3) -> UIViewController { | ||
let viewController = loadViewController(with: identifier) | ||
injectDependency(to: viewController, arg1: arg1, arg2: arg2, arg3: arg3) | ||
return viewController | ||
} | ||
|
||
private func loadViewController(with identifier: String) -> UIViewController { | ||
SwinjectStoryboard.pushInstantiatingStoryboard(self) | ||
let viewController = super.instantiateViewController(withIdentifier: identifier) | ||
SwinjectStoryboard.popInstantiatingStoryboard() | ||
return viewController | ||
} | ||
|
||
#endif | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// | ||
// SwinjectStoryboardExtensions.swift | ||
// SwinjectStoryboard | ||
// | ||
// Created by Malkevych Bohdan on 10.08.17. | ||
// Copyright © 2017 Swinject Contributors. All rights reserved. | ||
// | ||
|
||
import Swinject | ||
|
||
#if os(iOS) || os(OSX) || os(tvOS) | ||
extension Container { | ||
/// Adds a registration of the specified view or window controller that is configured in a storyboard. | ||
/// | ||
/// - Note: Do NOT explicitly resolve the controller registered by this method. | ||
/// The controller is intended to be resolved by `SwinjectStoryboard` implicitly. | ||
/// | ||
/// - Parameters: | ||
/// - controllerType: The controller type to register as a service type. | ||
/// The type is `UIViewController` in iOS, `NSViewController` or `NSWindowController` in OS X. | ||
/// - name: A registration name, which is used to differenciate from other registrations | ||
/// that have the same view or window controller type. | ||
/// - initCompleted: A closure to specifiy how the dependencies of the view or window controller are injected. | ||
/// It is invoked by the `Container` when the view or window controller is instantiated by `SwinjectStoryboard`. | ||
|
||
public func storyboardInitCompletedArg<C: Controller, Arg>(_ controllerType: C.Type, | ||
name: String? = nil, initCompleted: @escaping (Resolver, C, Arg) -> ()) { | ||
let factory = { (r: Resolver, c: Controller, arg: Arg) -> Container.Controller in | ||
initCompleted(r, c as! C, arg) | ||
return c | ||
} | ||
|
||
let option = SwinjectStoryboardOption(controllerType: controllerType) | ||
_register(Controller.self, factory: factory, name: name, option: option) | ||
} | ||
|
||
public func storyboardInitCompletedArgs<C: Controller, Arg1, Arg2>(_ controllerType: C.Type, | ||
name: String? = nil, | ||
initCompleted: @escaping (Resolver, C, Arg1, Arg2) -> ()) { | ||
let factory = { (r: Resolver, c: Controller, arg1: Arg1, arg2: Arg2) -> Container.Controller in | ||
initCompleted(r, c as! C, arg1, arg2) | ||
return c | ||
} | ||
|
||
let option = SwinjectStoryboardOption(controllerType: controllerType) | ||
_register(Controller.self, factory: factory, name: name, option: option) | ||
} | ||
|
||
public func storyboardInitCompletedArgs<C: Controller, Arg1, Arg2, Arg3>(_ controllerType: C.Type, | ||
name: String? = nil, | ||
initCompleted: @escaping (Resolver, C, Arg1, Arg2, Arg3) -> ()) { | ||
let factory = { (r: Resolver, c: Controller, arg1: Arg1, arg2: Arg2, arg3: Arg3) -> Container.Controller in | ||
initCompleted(r, c as! C, arg1, arg2, arg3) | ||
return c | ||
} | ||
|
||
let option = SwinjectStoryboardOption(controllerType: controllerType) | ||
_register(Controller.self, factory: factory, name: name, option: option) | ||
} | ||
} | ||
#endif | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, this file should probably be generated (see. Resolver.erb) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,7 @@ Pod::Spec.new do |s| | |
s.homepage = "https://github.com/Swinject/SwinjectStoryboard" | ||
s.license = 'MIT' | ||
s.author = 'Swinject Contributors' | ||
s.source = { :git => "https://github.com/Swinject/SwinjectStoryboard.git", :tag => s.version.to_s } | ||
s.source = { :git => "https://github.com/SeductiveMobile/SwinjectStoryboard.git", :tag => s.version.to_s } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
core_files = 'Sources/*.{swift,m,h}' | ||
s.ios.source_files = core_files, 'Sources/iOS-tvOS/*.{swift,h,m}' | ||
|
Large diffs are not rendered by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be more consistent to have API similar to Swinject, i.e.
instantiateViewController(withIdentifier: "SomeIdentifier", arguments: firstArg, secondArg)