This is alpha version. Works with Xcode 8.1 and Swift 3.
brew install appsquickly/core/typhoon
TyphoonSwift uses code generation to build your assembly. It runs as separate process (via terminal) and parses your source files on change. Once you change your assembly file and save, it parses it and generate "activated assembly" automatically.
- Setup typhoon to run with your Swift project
go to your project directory and run:
typhoon setup
that makes Typhoon.plist
file with settings.
- Run typhoon monitor
typhoon run
- Add generated files to your project.
Just drag results directory to your project ( see resultDirPath
inside Typhoon.plist
). It contains activated assemblies built from your assemblies and tiny typhoon runtime.
make sure that typhoon is up and running ( typhoon run
command), then you can create assemblies inside your assemblies directory.
Assemblies syntax is very similar to Typhoon Objc:
class CoreComponents : Assembly {
func manWith(_ name: String) -> Definition {
return Definition(withClass: Man.self) {
$0.injectProperty("name", with: name)
$0.setScope(Definition.Scope.ObjectGraph)
$0.injectProperty("brother", with: self.man())
}
}
func man() -> Definition {
return Definition(withClass: Man.self) { configuration in
configuration.injectProperty("name", with: "John")
configuration.injectProperty("brother", with: self.manWith("Alex"))
}
}
func manWithInitializer() -> Definition {
return Definition(withClass: Man.self) {
$0.setScope(Definition.Scope.Prototype)
$0.useInitializer("init(withName:)", with: { (m) in
m.injectArgument("Tom")
})
$0.injectMethod("setAdultAge")
$0.injectMethod("setValues(_:withAge:)") { (m) in
m.injectArgument("John")
m.injectArgument(21)
}
}
}
}
After you've done with assemblies, you should activate Typhoon (That instantiates all eager singletones)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
Typhoon.activateAssemblies()
return true
}
That's all, now you can inject your components anywhere in your project, just like:
class ViewController: UIViewController {
let man = CoreComponents.assembly.man()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
print("man.name=\(man.name)")
}
}
You can resolve all your definition through .assembly.<Definition-Method()>
Generated assembly has all your definitions methods, plus additional ways to resolve. See examples below:
// Resovle using definition method
let man = CoreComponents.assembly.manWithInitializer()
// Get all components matching Type
let men = CoreComponents.assembly.allComponentsForType() as [Man]
// Resolve by Key
let keyedMen = CoreComponents.assembly.component(forKey: "man") as Man?
// Inject using instance type
var woman = Woman()
CoreComponents.assembly.inject(&woman)
// Resolve by Type
let byTypeWoman = CoreComponents.assembly.componentForType() as Woman?
If you still have questions how to use it, try Example project (see Example subdirectory)
- Aleksey Garbarev - main idea and implementation
- Igor Vasilenko - huge effort and outcome in refactoring
- Valeriy Popov - swift2 -> swift 3 convertation. Moving dependencies to SPM
- German Saprykin - moving SPM dependencies to separate project to keep main project untouched on SPM updates
- You are welcome to be here :-)
TyphoonSwift is highly inspired by original Typhoon founded by Jasper Blues.
Solving circular references solution inspired by FieryCrucible DI framework.