Closed razvanred closed 3 years ago
@razvanred99 Thanks for the issue! I see two distinct issues here so I'm gonna break this up into two parts.
Regarding@BindsOptionalOf
, I think adding an optional dependency requirement could be a helpful feature for Cleanse. Off the top of my head, my thinking is that it would take the form of OptionalProvider<E>
so that it doesn't collide with Swift's Optional
type. I can draft an RFC and work with you to make sure the new feature meets your needs.
I'd like to learn more about how a subcomponent seed object (that isn't already bound into the graph) would be available to its parent. I'm confused how this would work because a Seed object can be unique to the subcomponent, and there could be multiple subcomponents alive at the same time. If there are multiple subcomponents, how would the parent know which Account
object to use?
Using Account
as an example probably isn't helpful since there's usually just 1 account at a time, but take for example an eBook reader application that supports multitasking by reading two different books at the same time. Let's say we create a Subcomponent
for displaying the reader screen when we tap on a book.
struct BookReaderComponent: Component {
typealias Root = ReaderViewController
typealias Seed = Book
// ...
When we want to display the two books side-by-side, we would call say:
func display(book1, book2) {
let reader1 = bookReaderComponent.build(book1)
let reader2 = bookReaderComponent.build(book2)
showViewControllers([reader1, reader2])
}
So in the parent graph, what would Book
be? The instance of book1
or book2
? Maybe it doesn't matter and the intended purpose is just a way to see if any subcomponent is alive?
@razvanred99 even in Dagger there's not a direct way to provide a Subcomponent's seed value to a parent graph. I didn't quite follow what was happening in the dagger.dev tutorial but you can do something like this (sorry, my Swift might be a bit rusty):
In your RootComponent
, create a class that acts as a holder: AccountStatusHolder
. That class can have a nullable account on it Account?
Then since the Subcomponent is a child of the RootComponent it can inject AccountStatusHolder
and set a value on it.
RootComponent
struct Account {
let email: String
}
class AccountStatusHolder {
var account: Account?
}
Subcomponent
class LoggedInHandler {
let accountStatusHolder: AccountStatusHolder
init(accountStatusHolder: AccountStatusHolder) {
self.accountStatusHolder = accountStatusHolder
}
func login(account: Account) {
accountStatusHolder.account = account
}
}
Let me know if that makes sense
@razvanred99 We currently do not have any plans to implement an optional binding provider. To achieve the same effect today, you could create a swift optional binding of your type and assign it to nil
.
binder
.bind(Database?.self)
.to(value: nil)
PRs welcome if you'd like to help add this feature!
Hi, I'm new to Cleanse, I'm trying to imitate the behaviour of the
@BindsOptionalOf
annotation from Dagger 2.More specifically, I'm trying to make a Component's Seed object available to its RootComponent.
If you're familiar with the dagger.dev ATM tutorial, at the last step the Account object bind in the UserCommandsRouter subcomponent is injected into the LoginCommand when available, through the
@BindsOptionalOf
annotation.UserCommandsRouter.java subcomponent:
LoginModule.java (included in the RootComponent):
And this is how I tried to imitate the UserCommandsRouter class in Swift:
LoginCommandModule.swift: