Closed ghost closed 10 years ago
We are not using method swizzling because is uses defaultFactory
, I don't like singleton for factory.
Second solution, with TyphoonRestoration seems that needed singleton too (in typhoonStoryboard method).
I think solution should use method swizzling and not use defaultFactory or other singletons
Thanks for great research! I never used UI State Restoration before - it is reason why TyphoonStoryboard didn't tested with this case.
Oh, It was indiscreet of me to use defaultFactory
.
I agree that singleton is not good, too, because it causes easily unwanted dependency.
But anyway, I think we must use something tricky such as above solutions whether we use singleton or not, is that light?
UI State Restoration is useful especially for large-scale applications, so I think it is good that Typhoon provides some feature to support UI State Restoration or documentation to make implementation easy.
I wish my research to be helpful for Typhoon project.
Thank you.
Yes @Masatz , great work! Thanks for your contribution.
We now have two advantages of doing "transparent" Storyboard integration using mix-ins:
Perhaps @alexgarbarev has another Idea on how to make the 2nd case work. But here's a suggestion on doing it using swizzling and but still not requiring singletons or modifying main.m (until now, we've done all Typhoon set-up in Assembly/app-delegate)
Thank you for your advices.
I removed swizzling and making default factory codes and I tried to implement TyphoonIntegratedAppDelegate
, as you described above.
As far as I know, app delegate's method which is called the first on launching app is application:willFinishLaunchingWithOption:
or application:didFinishLaunchingWithOption:
. So I moved codes to prepare factory and swizzle storyboard constructors into these methods with dispatch_once
, but it didn't work well. I set symbolic breakpoint to determine when storyboard was constructed, and it was turned out that storyboard was constructed before application:willFinishLaunchingWithOption:
or application:didFinishLaunchingWithOption:
was called.
So, I moved these codes to initialize
of TyphoonIntegratedAppDelegate
. Then, it worked well... but I'm not sure if this way is right or not.
Do you know good place to put these codes on except main.m?
I had idea and today I have a little time to implement this feature. Let me try..
This feature done! Typhoon will automatically swizzle initial UIStoryboard if needed at startup.
All you have to do is specifing initial factory. To specify initial factory two options available:
Option 1 implement in your AppDelegate -initialFactory method like tihs:
@implementation AppDelegate
...
- (TyphoonComponentFactory *)initialFactory
{
return [TyphoonBlockComponentFactory factoryWithAssembly:[MainAssembly assembly]];
}
...
@end
Option 2
Edit Info.plist
, add key TyphoonInitialAssemblies
as Array where values are assembly class names.
Like this:
Initial factory usage
If you specify initial storyboard in Info.plist
(UIMainStoryboardFile key), Typhoon will swizzle UIStoryboard to replace initial UIStoryboard with TyphoonStoryboard initialized with initial factory.
Typhoon tries to inject dependencies into your 'AppDelegate' class at startup. If initial factory has definition for your AppDelegate class, this definition will be used to inject dependencies. In any case, you can implement next method in AppDelegate to get initial factory:
- (void)typhoonSetFactory:(id)factory
(typhoonDidInject hook also available) Note: injection to AppDelegate performs before applicationDidFinishLaunching called
Great work Aleksey! This is looking really polished now.
Noted also that we can use this to get AppDelegate injection even if not using Storyboards. (As an alternative to pulling dependencies from Typhoon from within the AppDelegate).
@Masatz would you like to verify this one again? To test:
pod 'Typhoon', :head
. . once verified we'll push 2.1.0 to CocoaPods master.
Thank you!
I installed HEAD repository and I verified it worked very well. Excellent. We don't need to write codes to make key window and prepare initial view controller on AppDelegate anymore... very smart.
Again, thank you very much for your great work.
Thanks again Aleksey !!
I saw this page ( http://stackoverflow.com/questions/18998759/typhoon-assembly-and-storyboard-created-viewcontrollers ) and introduced TyphoonStoryboard to my project to inject to View Controllers instantiated from Storyboard, and it works well, but UI State Preservation/Restoration compatibility was lost in exchange for it.
To make UI State Preservation/Restoration be compatible with TyphoonStoryboard, I tried following solutions:
1. Exchanging constructors between UIStoryboard and TyphoonStoryboard
According to this page ( http://qiita.com/tomohisaota/items/eb7fca833f808d52b4c2 ), using run-time-method-swizzling provided by objc runtime, we can use TyphoonStoryboard as UIStoryboard. In this way, we can use "Main" storyboard on Info-Plist, and don't have to construct UIWindow, TyphoonStoryboard, and Root View Controller on application:didFinishLaunchingWithOptions:. Method exchanging seems to have to be performed before beginning of UI State Restoration process, so I added exchange codes to main() function:
main.m
I think this way is smart but method-exchanging seems to be tricky and risky. So I tried following way:
2. Using Restoration Class and manual preservation/restoration
I added Restoration Class instantiating view controllers from TyphoonStoryboard on restoration process, and injected restoration class on TyphoonAssembly subclass, and added codes to encode/decode root view controller manually on App Delegate.
MyAppDelegate.m
MyAssembly.m
TyphoonRestoration.m
This way doesn't need tricky technique such as method-exchanging but I think it's not smart.
Is there more suitable way to make UI State Preservation/Restoration be compatible with TyphoonStoryboard?