iOSアプリケーションの開発にMVVMアーキテクチャの考えを持ち込んで設計を見直そうという話をしました
MVVM for iOSMVVM for iOS@laiso@laiso03/12/201403/12/2014potatotips#5(at COOKPAD)potatotips#5(at COOKPAD)
View Slide
laiso is NOTlaiso is NOT ແ৬ແ৬http://lai.so/
ΤϯλʔϓϥΠζΤϯλʔϓϥΠζObjective-CObjective-Cͷੈքͱͷੈքͱ
มߋ͕πϥ͍มߋ͕πϥ͍iOSiOSΞϓϦέʔΞϓϦέʔγϣϯγϣϯFat & Massive ViewControllerGod object, SingletonUI testing is very hard
มߋʹཱ͔ͪ͏มߋʹཱ͔ͪ͏iOSiOSΞϓϦΞϓϦέʔγϣϯέʔγϣϯOSΞοϓσʔτʹΑΓΫϥΠΞϯτͷڥ͕ͲΜͲΜߋ৽͞ΕͯΏ͘ϢʔβʔαΠυͰಈ͘ͿΜݖݶӨڹ͕େ͖͘มߋʹϦεΫ͕͋Δ(࣭ཁٻ͕ߴ͍)ωΠςΟϒUIͷมߋHTML+JavaScriptͳͲΑΓॏ͘ͳΓ͕ͪ
ઃܭվળઃܭվળίʔυΛཧղ͍ͨ͘͢͠͠ςετΛॻ͖͍ͨ͘͢͠มߋʹڧ͘ͳΓɺߴʹ։ൃ͍ͨ͠
MVVMMVVM(Model View ViewModel)(Model View ViewModel)
MVVMMVVMWindows / .NETWPFSilverlightJavaScript FrameworkAngularJSKnockoutJS
MVCMVCMVVMMVVM
Cocoa vs MVVMCocoa vs MVVMϓϥοτϑΥʔϜຖʹMVCͷߟ͑ํҧ͏(Rails,Cocoa,Smalltalk)Controller != ViewControllerMVVM View == View+ViewController
ViewControllerViewControllerϏϡʔͷίϯτϩʔϥʔΞϓϦέʔγϣϯ/Ϟδϡʔϧ"ͷ"ίϯτϩʔϥʔͰͳ͍ରͷϏϡʔΛอ໋࣋ͯ͠ྩ͢Δ
ViewModelViewModelView-ModelɻϏϡʔͷͨΊͷϞσϧσʔλόΠϯσΟϯάͷΈͰσʔλΛϏϡʔͱଓϏϡʔͳ͠ͰΠϯλʔϑΣΠεΛૢ࡞Ͱ͖Δ
MVVMMVVMͷத৺ͱͳΔߟ͑ํͷத৺ͱͳΔߟ͑ํએݴతͳViewςϯϓϨʔτσʔλόΠϯσΟϯά
Storyboard(IB)Storyboard(IB)એݴతͳViewςϯϓϨʔτStoryboard != ViewதΞοϓϧͷಠࣗن֨ͷXMLςΩετϑΝΠϧXcode͕GUIσβΠϯπʔϧͱͯ͠ղऍ͢ΔɻຊϏϡʔΛએݴͯ͠ΠϕϯτΛଓ͢Δ͜ͱʮUIύʔπΛը໘ʹදࣔͤ͞ΔͨΊͷπʔϧʯҎ্ͷҙຯ߹͍͕͋Δ
σʔλόΠϯσΟϯάσʔλόΠϯσΟϯά = Co‐= Co‐coacoaόΠϯσΟϯάόΠϯσΟϯά??Mac OS X͚ͷσʔλόΠϯσΟϯάػߏiOSʹདྷͯͳ͍see "Cocoa Bindings Programming Topics"http://news.mynavi.jp/special/2005/cocoamvc/menu.html
σʔλόΠϯσΟϯάσʔλόΠϯσΟϯά = Re‐= Re‐activeCocoaactiveCocoahttps://github.com/ReactiveCocoa/ReactiveCocoa
ReactiveCocoaReactiveCocoaMac/iOSͰϦΞΫςΟϒϓϩάϥϛϯάΛ࣮ݱ͢ΔҝͷϥΠϒϥϦؔܕϓϩάϥϛϯά෩ͷݴޠDSL
ReactiveCocoaReactiveCocoaͱͱGitHubGitHubGitHubࣾͷਓୡΛϝΠϯʹ։ൃ͞Ε͍ͯΔGitHub͕Windows൛ΞϓϦέʔγϣϯΛ։ൃ͠ग़ͨ͋ͨ͠Γ͔Β׆ൃʹGitHubʹC#/.NETܥͷ࣮ྗऀ͕͍ΔɻXamarin/MonoͬͯΔͦ͏GitHubͷMacΞϓϦReactiveCocoaΛͬͯMVVMΛ࣮ݱ͍ͯ͠Δ
ReactiveCocoaReactiveCocoaมߋΛγάφϧͱ͍͏ΦϒδΣΫτͰදݱͰ͖ΔͷͰɺViewModelViewͷৄࡉΛΔඞཁ͕ͳ͍ViewModelΛରʹςετ͕ॻ͚Δ
RVMViewModelRVMViewModelReactiveCocoa/ReactiveViewModelಛఆͷγάφϧͷΠϯλʔϑΣΠεΛఆٛͨ͠ϕʔεΫϥεViewModelͰܧঝͯ͠͏
ViewModelViewModelΛࠐΉΛࠐΉViewControllerͷॳظԽ࣌ʹ// TipsListViewController- (id)init{// ...self.viewModel = [[TipsListViewModel alloc] init];return self;}
ViewModelViewModelΛࠐΉΛࠐΉStoryboardͷγʔέϯεͰInject// TipsListViewController- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {if ([[segue identifier] isEqualToString:@"showDetail"]) {NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];TipsDetailViewController *viewController = segue.destinationViewController;// ભҠઌͷViewModelΛॳظԽͯ͠ฦ͢viewController.viewModel = [self.viewModel detailViewModelForIndexPath:indexPath];}}
ViewModelViewModelͷ୯ମςετͷ୯ମςετit (@"ViewModelͷςετ", ^{TipsDetailViewModel *viewModel = [[TipsDetailViewModel alloc] initWithModel:tips]expect(viewModel.title).to.equal(@"MVVM for iOS");expect(viewModel.subTitle).to.equal(@"");expect(viewModel.author).to.equal(@"laiso");});
ProsProsUIͱϩδοΫͷςετ͘͢͠ͳΔ࠶ར༻͘͢͠ͳΔϦΞΫςΟϒUIԽͰͷԠੑ্
ConsConsهड़ྔ͕૿͑ΔReactiveCocoaͷޠኮΛशಘ͢Δඞཁ͕͋Δ࣮ݧతͰ࣮ફ͢Δͷ͕͍͠ϑϨʔϜϫʔΫଆͷڧ੍ྗͳ͍ͷͰͨͩʹͳͬͯΠϚΠνͳײ͡ͰऴΘΔՄೳੑ͋ΔUIʹର͢ΔςετΧόʔͰ͖ͳ͍
͜Ε͔Β͜Ε͔Β1. ෳͷ։ൃऀ͕͔͔ΘΔΑ͏ͳෳࡶͰنͷେ͖ͳΞϓϦέʔγϣϯΛ͏·͘։ൃͰ͖ΔΑ͏ʹ͢Δ2. ςετͰอޢͰ͖ΔൣғΛ૿ͯ͠ϦϑΝΫλϦϯάͰίʔυͷഊΛ͗ߴʹϦϦʔεͰ͖ΔΑ͏ʹ͢Δ3. ํ๏ͷಋೖͰͳ͘എܠͷ՝ʹؔ৺Λ࣋ͪࣗͨͪͰߟ͑Δ͜ͱͰվળ͍ͯ͘͠
ࢀߟࢿྉࢀߟࢿྉCode Reuse with MVVMModel-View-ViewModel for iOS | Teehan+LaxReactiveCocoa/Documentation/FrameworkOverview.mdat master · ReactiveCocoa/ReactiveCocoaGUI Architectures
Functional Reactive Program‐Functional Reactive Program‐ming on iOSming on iOShttps://leanpub.com/iosfrp
Xamarin.iOSXamarin.iOSC#͚ͷMVVMαϙʔτϥΠϒϥϦhttps://github.com/MvvmCross/MvvmCrosshttps://github.com/reactiveui/ReactiveUI
Thank YouThank You