diff --git a/.gitignore b/.gitignore index d522f94..39182e0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,18 @@ -# CocoaPods -# -# We recommend against adding the Pods directory to your .gitignore. However -# you should judge for yourself, the pros and cons are mentioned at: -# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control? -# -# Pods/ +# Xcode +.DS_Store +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +profile +*.moved-aside +DerivedData +.idea/ +/Build diff --git a/VIPER-SWIFT.xcodeproj/project.pbxproj b/VIPER-SWIFT.xcodeproj/project.pbxproj new file mode 100755 index 0000000..1af8f9f --- /dev/null +++ b/VIPER-SWIFT.xcodeproj/project.pbxproj @@ -0,0 +1,844 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 261FA1B919414A720029F589 /* AppDependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA17219414A720029F589 /* AppDependencies.swift */; }; + 261FA1BC19414A720029F589 /* NSCalendar+CalendarAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA17919414A720029F589 /* NSCalendar+CalendarAdditions.swift */; }; + 261FA1BE19414A720029F589 /* Clock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA17D19414A720029F589 /* Clock.swift */; }; + 261FA1BF19414A720029F589 /* DeviceClock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA17E19414A720029F589 /* DeviceClock.swift */; }; + 261FA1C019414A720029F589 /* NearTermDateRelation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA18019414A720029F589 /* NearTermDateRelation.swift */; }; + 261FA1C119414A720029F589 /* TodoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA18119414A720029F589 /* TodoItem.swift */; }; + 261FA1C219414A720029F589 /* CoreDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA18319414A720029F589 /* CoreDataStore.swift */; }; + 261FA1C419414A720029F589 /* TODO.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 261FA18719414A720029F589 /* TODO.xcdatamodeld */; }; + 261FA1C519414A720029F589 /* RootWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA18A19414A720029F589 /* RootWireframe.swift */; }; + 261FA1C619414A720029F589 /* AddInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA18F19414A720029F589 /* AddInteractor.swift */; }; + 261FA1C719414A720029F589 /* AddDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA19119414A720029F589 /* AddDataManager.swift */; }; + 261FA1C819414A720029F589 /* AddModuleDelegateInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA19419414A720029F589 /* AddModuleDelegateInterface.swift */; }; + 261FA1C919414A720029F589 /* AddModuleInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA19519414A720029F589 /* AddModuleInterface.swift */; }; + 261FA1CA19414A720029F589 /* AddPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA19819414A720029F589 /* AddPresenter.swift */; }; + 261FA1CB19414A720029F589 /* AddDismissalTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA19A19414A720029F589 /* AddDismissalTransition.swift */; }; + 261FA1CC19414A720029F589 /* AddPresentationTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA19B19414A720029F589 /* AddPresentationTransition.swift */; }; + 261FA1CD19414A720029F589 /* AddViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA19D19414A720029F589 /* AddViewController.swift */; }; + 261FA1CE19414A720029F589 /* AddViewInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA19E19414A720029F589 /* AddViewInterface.swift */; }; + 261FA1CF19414A720029F589 /* AddWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1A019414A720029F589 /* AddWireframe.swift */; }; + 261FA1D019414A720029F589 /* ListInteractor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1A419414A720029F589 /* ListInteractor.swift */; }; + 261FA1D119414A720029F589 /* ListInteractorIO.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1A519414A720029F589 /* ListInteractorIO.swift */; }; + 261FA1D219414A720029F589 /* UpcomingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1A619414A720029F589 /* UpcomingItem.swift */; }; + 261FA1D319414A720029F589 /* ListDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1A819414A720029F589 /* ListDataManager.swift */; }; + 261FA1D419414A720029F589 /* ListModuleInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1AB19414A720029F589 /* ListModuleInterface.swift */; }; + 261FA1D519414A720029F589 /* ListPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1AE19414A720029F589 /* ListPresenter.swift */; }; + 261FA1D619414A720029F589 /* UpcomingDisplayData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1AF19414A720029F589 /* UpcomingDisplayData.swift */; }; + 261FA1D719414A720029F589 /* UpcomingDisplayDataCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B019414A720029F589 /* UpcomingDisplayDataCollection.swift */; }; + 261FA1D819414A720029F589 /* UpcomingDisplayItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B119414A720029F589 /* UpcomingDisplayItem.swift */; }; + 261FA1D919414A720029F589 /* UpcomingDisplaySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B219414A720029F589 /* UpcomingDisplaySection.swift */; }; + 261FA1DA19414A720029F589 /* ListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B419414A720029F589 /* ListViewController.swift */; }; + 261FA1DB19414A720029F589 /* ListViewInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B519414A720029F589 /* ListViewInterface.swift */; }; + 261FA1DC19414A720029F589 /* ListWireframe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B719414A720029F589 /* ListWireframe.swift */; }; + 261FA1E719414CBE0029F589 /* ManagedTodoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1E619414CBE0029F589 /* ManagedTodoItem.swift */; }; + 261FA1EC1942320E0029F589 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 261FA1EA1942320E0029F589 /* Main.storyboard */; }; + 261FA1EE194232180029F589 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 261FA1ED194232180029F589 /* Images.xcassets */; }; + 26A605EB1942A1EE0036C71F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26A605EA1942A1EE0036C71F /* AppDelegate.swift */; }; + 26D96F9C19428C3600F117F5 /* CalendarTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26D96F9B19428C3600F117F5 /* CalendarTests.swift */; }; + 26D96F9D19428C7E00F117F5 /* NSCalendar+CalendarAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA17919414A720029F589 /* NSCalendar+CalendarAdditions.swift */; }; + 26D96F9E19428D8100F117F5 /* NearTermDateRelation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA18019414A720029F589 /* NearTermDateRelation.swift */; }; + 26D96FA11942912A00F117F5 /* UpcomingDisplayData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1AF19414A720029F589 /* UpcomingDisplayData.swift */; }; + 26D96FA21942912A00F117F5 /* UpcomingDisplayDataCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B019414A720029F589 /* UpcomingDisplayDataCollection.swift */; }; + 26D96FA31942912A00F117F5 /* UpcomingDisplayItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B119414A720029F589 /* UpcomingDisplayItem.swift */; }; + 26D96FA41942912A00F117F5 /* UpcomingDisplaySection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B219414A720029F589 /* UpcomingDisplaySection.swift */; }; + 26D96FA51942912A00F117F5 /* ListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B419414A720029F589 /* ListViewController.swift */; }; + 26D96FA61942913600F117F5 /* ListViewInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1B519414A720029F589 /* ListViewInterface.swift */; }; + 26D96FA71942913B00F117F5 /* ListModuleInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1AB19414A720029F589 /* ListModuleInterface.swift */; }; + 26D96FA81942915D00F117F5 /* UpcomingItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1A619414A720029F589 /* UpcomingItem.swift */; }; + 26D96FA91942932A00F117F5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 261FA1EA1942320E0029F589 /* Main.storyboard */; }; + 26D96FAA1942932A00F117F5 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 261FA1ED194232180029F589 /* Images.xcassets */; }; + 26D96FAC1942967900F117F5 /* RelativeDateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26D96FAB1942967900F117F5 /* RelativeDateTests.swift */; }; + 26D96FAE19429A9000F117F5 /* DataTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26D96FAD19429A9000F117F5 /* DataTests.swift */; }; + 26D96FAF19429AD000F117F5 /* ManagedTodoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1E619414CBE0029F589 /* ManagedTodoItem.swift */; }; + 26D96FB019429AD000F117F5 /* CoreDataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA18319414A720029F589 /* CoreDataStore.swift */; }; + 26D96FB119429B1A00F117F5 /* TodoItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA18119414A720029F589 /* TodoItem.swift */; }; + 26D96FB219429B1A00F117F5 /* ListDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 261FA1A819414A720029F589 /* ListDataManager.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 261FA1611941497E0029F589 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 261FA1461941497E0029F589 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 261FA14D1941497E0029F589; + remoteInfo = "VIPER-SWIFT"; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 261FA14E1941497E0029F589 /* VIPER-SWIFT.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "VIPER-SWIFT.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 261FA1601941497E0029F589 /* VIPER-SWIFTTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "VIPER-SWIFTTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + 261FA1651941497E0029F589 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 261FA17219414A720029F589 /* AppDependencies.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDependencies.swift; sourceTree = ""; }; + 261FA17919414A720029F589 /* NSCalendar+CalendarAdditions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSCalendar+CalendarAdditions.swift"; sourceTree = ""; }; + 261FA17D19414A720029F589 /* Clock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Clock.swift; sourceTree = ""; }; + 261FA17E19414A720029F589 /* DeviceClock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeviceClock.swift; sourceTree = ""; }; + 261FA18019414A720029F589 /* NearTermDateRelation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NearTermDateRelation.swift; sourceTree = ""; }; + 261FA18119414A720029F589 /* TodoItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TodoItem.swift; sourceTree = ""; }; + 261FA18319414A720029F589 /* CoreDataStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CoreDataStore.swift; sourceTree = ""; }; + 261FA18819414A720029F589 /* TODO.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = TODO.xcdatamodel; sourceTree = ""; }; + 261FA18A19414A720029F589 /* RootWireframe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RootWireframe.swift; sourceTree = ""; }; + 261FA18F19414A720029F589 /* AddInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddInteractor.swift; sourceTree = ""; }; + 261FA19119414A720029F589 /* AddDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddDataManager.swift; sourceTree = ""; }; + 261FA19419414A720029F589 /* AddModuleDelegateInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddModuleDelegateInterface.swift; sourceTree = ""; }; + 261FA19519414A720029F589 /* AddModuleInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddModuleInterface.swift; sourceTree = ""; }; + 261FA19819414A720029F589 /* AddPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddPresenter.swift; sourceTree = ""; }; + 261FA19A19414A720029F589 /* AddDismissalTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddDismissalTransition.swift; sourceTree = ""; }; + 261FA19B19414A720029F589 /* AddPresentationTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddPresentationTransition.swift; sourceTree = ""; }; + 261FA19D19414A720029F589 /* AddViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddViewController.swift; sourceTree = ""; }; + 261FA19E19414A720029F589 /* AddViewInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddViewInterface.swift; sourceTree = ""; }; + 261FA1A019414A720029F589 /* AddWireframe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddWireframe.swift; sourceTree = ""; }; + 261FA1A419414A720029F589 /* ListInteractor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListInteractor.swift; sourceTree = ""; }; + 261FA1A519414A720029F589 /* ListInteractorIO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListInteractorIO.swift; sourceTree = ""; }; + 261FA1A619414A720029F589 /* UpcomingItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpcomingItem.swift; sourceTree = ""; }; + 261FA1A819414A720029F589 /* ListDataManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListDataManager.swift; sourceTree = ""; }; + 261FA1AB19414A720029F589 /* ListModuleInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListModuleInterface.swift; sourceTree = ""; }; + 261FA1AE19414A720029F589 /* ListPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListPresenter.swift; sourceTree = ""; }; + 261FA1AF19414A720029F589 /* UpcomingDisplayData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpcomingDisplayData.swift; sourceTree = ""; }; + 261FA1B019414A720029F589 /* UpcomingDisplayDataCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpcomingDisplayDataCollection.swift; sourceTree = ""; }; + 261FA1B119414A720029F589 /* UpcomingDisplayItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpcomingDisplayItem.swift; sourceTree = ""; }; + 261FA1B219414A720029F589 /* UpcomingDisplaySection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpcomingDisplaySection.swift; sourceTree = ""; }; + 261FA1B419414A720029F589 /* ListViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListViewController.swift; sourceTree = ""; }; + 261FA1B519414A720029F589 /* ListViewInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListViewInterface.swift; sourceTree = ""; }; + 261FA1B719414A720029F589 /* ListWireframe.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListWireframe.swift; sourceTree = ""; }; + 261FA1E619414CBE0029F589 /* ManagedTodoItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ManagedTodoItem.swift; sourceTree = ""; }; + 261FA1E819414E600029F589 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 261FA1EB1942320E0029F589 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = "VIPER-SWIFT/Base.lproj/Main.storyboard"; sourceTree = SOURCE_ROOT; }; + 261FA1ED194232180029F589 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = "VIPER-SWIFT/Images.xcassets"; sourceTree = SOURCE_ROOT; }; + 26A605EA1942A1EE0036C71F /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 26D96F9B19428C3600F117F5 /* CalendarTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CalendarTests.swift; sourceTree = ""; }; + 26D96FAB1942967900F117F5 /* RelativeDateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelativeDateTests.swift; sourceTree = ""; }; + 26D96FAD19429A9000F117F5 /* DataTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 261FA14B1941497E0029F589 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 261FA15D1941497E0029F589 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 261FA1451941497E0029F589 = { + isa = PBXGroup; + children = ( + 261FA1501941497E0029F589 /* VIPER-SWIFT */, + 261FA1631941497E0029F589 /* VIPER-SWIFTTests */, + 261FA14F1941497E0029F589 /* Products */, + ); + sourceTree = ""; + }; + 261FA14F1941497E0029F589 /* Products */ = { + isa = PBXGroup; + children = ( + 261FA14E1941497E0029F589 /* VIPER-SWIFT.app */, + 261FA1601941497E0029F589 /* VIPER-SWIFTTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 261FA1501941497E0029F589 /* VIPER-SWIFT */ = { + isa = PBXGroup; + children = ( + 261FA17019414A720029F589 /* Classes */, + 261FA1DD19414AC20029F589 /* Resources */, + 261FA1DE19414AC60029F589 /* Supporting Files */, + ); + path = "VIPER-SWIFT"; + sourceTree = ""; + }; + 261FA1631941497E0029F589 /* VIPER-SWIFTTests */ = { + isa = PBXGroup; + children = ( + 26D96F9B19428C3600F117F5 /* CalendarTests.swift */, + 26D96FAD19429A9000F117F5 /* DataTests.swift */, + 26D96FAB1942967900F117F5 /* RelativeDateTests.swift */, + 261FA1641941497E0029F589 /* Supporting Files */, + ); + path = "VIPER-SWIFTTests"; + sourceTree = ""; + }; + 261FA1641941497E0029F589 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 261FA1651941497E0029F589 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 261FA17019414A720029F589 /* Classes */ = { + isa = PBXGroup; + children = ( + 261FA17319414A720029F589 /* Common */, + 261FA18B19414A720029F589 /* Modules */, + 26A605EA1942A1EE0036C71F /* AppDelegate.swift */, + 261FA17219414A720029F589 /* AppDependencies.swift */, + ); + path = Classes; + sourceTree = ""; + }; + 261FA17319414A720029F589 /* Common */ = { + isa = PBXGroup; + children = ( + 261FA17419414A720029F589 /* Categories */, + 261FA17C19414A720029F589 /* Clock */, + 261FA17F19414A720029F589 /* Model */, + 261FA18219414A720029F589 /* Store */, + 261FA18919414A720029F589 /* View */, + ); + path = Common; + sourceTree = ""; + }; + 261FA17419414A720029F589 /* Categories */ = { + isa = PBXGroup; + children = ( + 261FA17919414A720029F589 /* NSCalendar+CalendarAdditions.swift */, + ); + path = Categories; + sourceTree = ""; + }; + 261FA17C19414A720029F589 /* Clock */ = { + isa = PBXGroup; + children = ( + 261FA17D19414A720029F589 /* Clock.swift */, + 261FA17E19414A720029F589 /* DeviceClock.swift */, + ); + path = Clock; + sourceTree = ""; + }; + 261FA17F19414A720029F589 /* Model */ = { + isa = PBXGroup; + children = ( + 261FA18019414A720029F589 /* NearTermDateRelation.swift */, + 261FA18119414A720029F589 /* TodoItem.swift */, + ); + path = Model; + sourceTree = ""; + }; + 261FA18219414A720029F589 /* Store */ = { + isa = PBXGroup; + children = ( + 261FA18419414A720029F589 /* Entities */, + 261FA18319414A720029F589 /* CoreDataStore.swift */, + 261FA18719414A720029F589 /* TODO.xcdatamodeld */, + ); + path = Store; + sourceTree = ""; + }; + 261FA18419414A720029F589 /* Entities */ = { + isa = PBXGroup; + children = ( + 261FA1E619414CBE0029F589 /* ManagedTodoItem.swift */, + ); + path = Entities; + sourceTree = ""; + }; + 261FA18919414A720029F589 /* View */ = { + isa = PBXGroup; + children = ( + 261FA18A19414A720029F589 /* RootWireframe.swift */, + ); + path = View; + sourceTree = ""; + }; + 261FA18B19414A720029F589 /* Modules */ = { + isa = PBXGroup; + children = ( + 261FA18C19414A720029F589 /* Add */, + 261FA1A119414A720029F589 /* List */, + ); + path = Modules; + sourceTree = ""; + }; + 261FA18C19414A720029F589 /* Add */ = { + isa = PBXGroup; + children = ( + 261FA18D19414A720029F589 /* Application Logic */, + 261FA19319414A720029F589 /* Module Interface */, + 261FA19619414A720029F589 /* User Interface */, + ); + path = Add; + sourceTree = ""; + }; + 261FA18D19414A720029F589 /* Application Logic */ = { + isa = PBXGroup; + children = ( + 261FA18E19414A720029F589 /* Interactor */, + 261FA19019414A720029F589 /* Manager */, + 261FA19219414A720029F589 /* Model */, + ); + path = "Application Logic"; + sourceTree = ""; + }; + 261FA18E19414A720029F589 /* Interactor */ = { + isa = PBXGroup; + children = ( + 261FA18F19414A720029F589 /* AddInteractor.swift */, + ); + path = Interactor; + sourceTree = ""; + }; + 261FA19019414A720029F589 /* Manager */ = { + isa = PBXGroup; + children = ( + 261FA19119414A720029F589 /* AddDataManager.swift */, + ); + path = Manager; + sourceTree = ""; + }; + 261FA19219414A720029F589 /* Model */ = { + isa = PBXGroup; + children = ( + ); + path = Model; + sourceTree = ""; + }; + 261FA19319414A720029F589 /* Module Interface */ = { + isa = PBXGroup; + children = ( + 261FA19419414A720029F589 /* AddModuleDelegateInterface.swift */, + 261FA19519414A720029F589 /* AddModuleInterface.swift */, + ); + path = "Module Interface"; + sourceTree = ""; + }; + 261FA19619414A720029F589 /* User Interface */ = { + isa = PBXGroup; + children = ( + 261FA19719414A720029F589 /* Presenter */, + 261FA19919414A720029F589 /* Transition */, + 261FA19C19414A720029F589 /* View */, + 261FA19F19414A720029F589 /* Wireframe */, + ); + path = "User Interface"; + sourceTree = ""; + }; + 261FA19719414A720029F589 /* Presenter */ = { + isa = PBXGroup; + children = ( + 261FA19819414A720029F589 /* AddPresenter.swift */, + ); + path = Presenter; + sourceTree = ""; + }; + 261FA19919414A720029F589 /* Transition */ = { + isa = PBXGroup; + children = ( + 261FA19A19414A720029F589 /* AddDismissalTransition.swift */, + 261FA19B19414A720029F589 /* AddPresentationTransition.swift */, + ); + path = Transition; + sourceTree = ""; + }; + 261FA19C19414A720029F589 /* View */ = { + isa = PBXGroup; + children = ( + 261FA19D19414A720029F589 /* AddViewController.swift */, + 261FA19E19414A720029F589 /* AddViewInterface.swift */, + ); + path = View; + sourceTree = ""; + }; + 261FA19F19414A720029F589 /* Wireframe */ = { + isa = PBXGroup; + children = ( + 261FA1A019414A720029F589 /* AddWireframe.swift */, + ); + path = Wireframe; + sourceTree = ""; + }; + 261FA1A119414A720029F589 /* List */ = { + isa = PBXGroup; + children = ( + 261FA1A219414A720029F589 /* Application Logic */, + 261FA1AA19414A720029F589 /* Module Interface */, + 261FA1AC19414A720029F589 /* User Interface */, + ); + path = List; + sourceTree = ""; + }; + 261FA1A219414A720029F589 /* Application Logic */ = { + isa = PBXGroup; + children = ( + 261FA1A319414A720029F589 /* Interactor */, + 261FA1A719414A720029F589 /* Manager */, + 261FA1A919414A720029F589 /* Model */, + ); + path = "Application Logic"; + sourceTree = ""; + }; + 261FA1A319414A720029F589 /* Interactor */ = { + isa = PBXGroup; + children = ( + 261FA1A419414A720029F589 /* ListInteractor.swift */, + 261FA1A519414A720029F589 /* ListInteractorIO.swift */, + 261FA1A619414A720029F589 /* UpcomingItem.swift */, + ); + path = Interactor; + sourceTree = ""; + }; + 261FA1A719414A720029F589 /* Manager */ = { + isa = PBXGroup; + children = ( + 261FA1A819414A720029F589 /* ListDataManager.swift */, + ); + path = Manager; + sourceTree = ""; + }; + 261FA1A919414A720029F589 /* Model */ = { + isa = PBXGroup; + children = ( + ); + path = Model; + sourceTree = ""; + }; + 261FA1AA19414A720029F589 /* Module Interface */ = { + isa = PBXGroup; + children = ( + 261FA1AB19414A720029F589 /* ListModuleInterface.swift */, + ); + path = "Module Interface"; + sourceTree = ""; + }; + 261FA1AC19414A720029F589 /* User Interface */ = { + isa = PBXGroup; + children = ( + 261FA1AD19414A720029F589 /* Presenter */, + 261FA1B319414A720029F589 /* View */, + 261FA1B619414A720029F589 /* Wireframe */, + ); + path = "User Interface"; + sourceTree = ""; + }; + 261FA1AD19414A720029F589 /* Presenter */ = { + isa = PBXGroup; + children = ( + 261FA1AE19414A720029F589 /* ListPresenter.swift */, + 261FA1AF19414A720029F589 /* UpcomingDisplayData.swift */, + 261FA1B019414A720029F589 /* UpcomingDisplayDataCollection.swift */, + 261FA1B119414A720029F589 /* UpcomingDisplayItem.swift */, + 261FA1B219414A720029F589 /* UpcomingDisplaySection.swift */, + ); + path = Presenter; + sourceTree = ""; + }; + 261FA1B319414A720029F589 /* View */ = { + isa = PBXGroup; + children = ( + 261FA1B419414A720029F589 /* ListViewController.swift */, + 261FA1B519414A720029F589 /* ListViewInterface.swift */, + ); + path = View; + sourceTree = ""; + }; + 261FA1B619414A720029F589 /* Wireframe */ = { + isa = PBXGroup; + children = ( + 261FA1B719414A720029F589 /* ListWireframe.swift */, + ); + path = Wireframe; + sourceTree = ""; + }; + 261FA1DD19414AC20029F589 /* Resources */ = { + isa = PBXGroup; + children = ( + 261FA1EA1942320E0029F589 /* Main.storyboard */, + 261FA1ED194232180029F589 /* Images.xcassets */, + ); + name = Resources; + path = "../../../../Documents/Repos/VIPER-TODO-SWIFT/viper-todo-swift/VIPER TODO/Resources"; + sourceTree = ""; + }; + 261FA1DE19414AC60029F589 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 261FA1E819414E600029F589 /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 261FA14D1941497E0029F589 /* VIPER-SWIFT */ = { + isa = PBXNativeTarget; + buildConfigurationList = 261FA16A1941497E0029F589 /* Build configuration list for PBXNativeTarget "VIPER-SWIFT" */; + buildPhases = ( + 261FA14A1941497E0029F589 /* Sources */, + 261FA14B1941497E0029F589 /* Frameworks */, + 261FA14C1941497E0029F589 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "VIPER-SWIFT"; + productName = "VIPER-SWIFT"; + productReference = 261FA14E1941497E0029F589 /* VIPER-SWIFT.app */; + productType = "com.apple.product-type.application"; + }; + 261FA15F1941497E0029F589 /* VIPER-SWIFTTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 261FA16D1941497E0029F589 /* Build configuration list for PBXNativeTarget "VIPER-SWIFTTests" */; + buildPhases = ( + 261FA15C1941497E0029F589 /* Sources */, + 261FA15D1941497E0029F589 /* Frameworks */, + 261FA15E1941497E0029F589 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 261FA1621941497E0029F589 /* PBXTargetDependency */, + ); + name = "VIPER-SWIFTTests"; + productName = "VIPER-SWIFTTests"; + productReference = 261FA1601941497E0029F589 /* VIPER-SWIFTTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 261FA1461941497E0029F589 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0600; + ORGANIZATIONNAME = "Conrad Stoll"; + TargetAttributes = { + 261FA14D1941497E0029F589 = { + CreatedOnToolsVersion = 6.0; + }; + 261FA15F1941497E0029F589 = { + CreatedOnToolsVersion = 6.0; + TestTargetID = 261FA14D1941497E0029F589; + }; + }; + }; + buildConfigurationList = 261FA1491941497E0029F589 /* Build configuration list for PBXProject "VIPER-SWIFT" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 261FA1451941497E0029F589; + productRefGroup = 261FA14F1941497E0029F589 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 261FA14D1941497E0029F589 /* VIPER-SWIFT */, + 261FA15F1941497E0029F589 /* VIPER-SWIFTTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 261FA14C1941497E0029F589 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 261FA1EE194232180029F589 /* Images.xcassets in Resources */, + 261FA1EC1942320E0029F589 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 261FA15E1941497E0029F589 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 26D96FA91942932A00F117F5 /* Main.storyboard in Resources */, + 26D96FAA1942932A00F117F5 /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 261FA14A1941497E0029F589 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 261FA1C719414A720029F589 /* AddDataManager.swift in Sources */, + 261FA1D119414A720029F589 /* ListInteractorIO.swift in Sources */, + 261FA1D719414A720029F589 /* UpcomingDisplayDataCollection.swift in Sources */, + 261FA1D219414A720029F589 /* UpcomingItem.swift in Sources */, + 261FA1D519414A720029F589 /* ListPresenter.swift in Sources */, + 261FA1D419414A720029F589 /* ListModuleInterface.swift in Sources */, + 261FA1B919414A720029F589 /* AppDependencies.swift in Sources */, + 261FA1D619414A720029F589 /* UpcomingDisplayData.swift in Sources */, + 261FA1C619414A720029F589 /* AddInteractor.swift in Sources */, + 261FA1D919414A720029F589 /* UpcomingDisplaySection.swift in Sources */, + 261FA1C819414A720029F589 /* AddModuleDelegateInterface.swift in Sources */, + 261FA1BF19414A720029F589 /* DeviceClock.swift in Sources */, + 261FA1DA19414A720029F589 /* ListViewController.swift in Sources */, + 261FA1BE19414A720029F589 /* Clock.swift in Sources */, + 261FA1C519414A720029F589 /* RootWireframe.swift in Sources */, + 261FA1C419414A720029F589 /* TODO.xcdatamodeld in Sources */, + 261FA1CD19414A720029F589 /* AddViewController.swift in Sources */, + 261FA1C119414A720029F589 /* TodoItem.swift in Sources */, + 26A605EB1942A1EE0036C71F /* AppDelegate.swift in Sources */, + 261FA1CB19414A720029F589 /* AddDismissalTransition.swift in Sources */, + 261FA1C219414A720029F589 /* CoreDataStore.swift in Sources */, + 261FA1CC19414A720029F589 /* AddPresentationTransition.swift in Sources */, + 261FA1C919414A720029F589 /* AddModuleInterface.swift in Sources */, + 261FA1D319414A720029F589 /* ListDataManager.swift in Sources */, + 261FA1CA19414A720029F589 /* AddPresenter.swift in Sources */, + 261FA1D019414A720029F589 /* ListInteractor.swift in Sources */, + 261FA1C019414A720029F589 /* NearTermDateRelation.swift in Sources */, + 261FA1E719414CBE0029F589 /* ManagedTodoItem.swift in Sources */, + 261FA1D819414A720029F589 /* UpcomingDisplayItem.swift in Sources */, + 261FA1BC19414A720029F589 /* NSCalendar+CalendarAdditions.swift in Sources */, + 261FA1DB19414A720029F589 /* ListViewInterface.swift in Sources */, + 261FA1DC19414A720029F589 /* ListWireframe.swift in Sources */, + 261FA1CE19414A720029F589 /* AddViewInterface.swift in Sources */, + 261FA1CF19414A720029F589 /* AddWireframe.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 261FA15C1941497E0029F589 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 26D96FB219429B1A00F117F5 /* ListDataManager.swift in Sources */, + 26D96FAF19429AD000F117F5 /* ManagedTodoItem.swift in Sources */, + 26D96F9D19428C7E00F117F5 /* NSCalendar+CalendarAdditions.swift in Sources */, + 26D96FAC1942967900F117F5 /* RelativeDateTests.swift in Sources */, + 26D96FAE19429A9000F117F5 /* DataTests.swift in Sources */, + 26D96FA71942913B00F117F5 /* ListModuleInterface.swift in Sources */, + 26D96FA41942912A00F117F5 /* UpcomingDisplaySection.swift in Sources */, + 26D96FA31942912A00F117F5 /* UpcomingDisplayItem.swift in Sources */, + 26D96F9C19428C3600F117F5 /* CalendarTests.swift in Sources */, + 26D96FA61942913600F117F5 /* ListViewInterface.swift in Sources */, + 26D96FB019429AD000F117F5 /* CoreDataStore.swift in Sources */, + 26D96FA11942912A00F117F5 /* UpcomingDisplayData.swift in Sources */, + 26D96FA81942915D00F117F5 /* UpcomingItem.swift in Sources */, + 26D96F9E19428D8100F117F5 /* NearTermDateRelation.swift in Sources */, + 26D96FA51942912A00F117F5 /* ListViewController.swift in Sources */, + 26D96FB119429B1A00F117F5 /* TodoItem.swift in Sources */, + 26D96FA21942912A00F117F5 /* UpcomingDisplayDataCollection.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 261FA1621941497E0029F589 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 261FA14D1941497E0029F589 /* VIPER-SWIFT */; + targetProxy = 261FA1611941497E0029F589 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 261FA1EA1942320E0029F589 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 261FA1EB1942320E0029F589 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 261FA1681941497E0029F589 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + METAL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 261FA1691941497E0029F589 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + METAL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 261FA16B1941497E0029F589 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "VIPER-SWIFT/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 261FA16C1941497E0029F589 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + INFOPLIST_FILE = "VIPER-SWIFT/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 261FA16E1941497E0029F589 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/VIPER-SWIFT.app/VIPER-SWIFT"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = "VIPER-SWIFTTests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + }; + name = Debug; + }; + 261FA16F1941497E0029F589 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/VIPER-SWIFT.app/VIPER-SWIFT"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = "VIPER-SWIFTTests/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUNDLE_LOADER)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 261FA1491941497E0029F589 /* Build configuration list for PBXProject "VIPER-SWIFT" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 261FA1681941497E0029F589 /* Debug */, + 261FA1691941497E0029F589 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 261FA16A1941497E0029F589 /* Build configuration list for PBXNativeTarget "VIPER-SWIFT" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 261FA16B1941497E0029F589 /* Debug */, + 261FA16C1941497E0029F589 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 261FA16D1941497E0029F589 /* Build configuration list for PBXNativeTarget "VIPER-SWIFTTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 261FA16E1941497E0029F589 /* Debug */, + 261FA16F1941497E0029F589 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + 261FA18719414A720029F589 /* TODO.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + 261FA18819414A720029F589 /* TODO.xcdatamodel */, + ); + currentVersion = 261FA18819414A720029F589 /* TODO.xcdatamodel */; + path = TODO.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ + }; + rootObject = 261FA1461941497E0029F589 /* Project object */; +} diff --git a/VIPER-SWIFT.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/VIPER-SWIFT.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..08dddca --- /dev/null +++ b/VIPER-SWIFT.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/VIPER-SWIFT/Base.lproj/Main.storyboard b/VIPER-SWIFT/Base.lproj/Main.storyboard new file mode 100755 index 0000000..20f9ede --- /dev/null +++ b/VIPER-SWIFT/Base.lproj/Main.storyboard @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/VIPER-SWIFT/Classes/AppDelegate.swift b/VIPER-SWIFT/Classes/AppDelegate.swift new file mode 100755 index 0000000..3ba121a --- /dev/null +++ b/VIPER-SWIFT/Classes/AppDelegate.swift @@ -0,0 +1,23 @@ +// +// AppDelegate.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Conrad Stoll. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? + + let appDependencies = AppDependencies() + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { + appDependencies.installRootViewControllerIntoWindow(window!) + + return true + } +} + diff --git a/VIPER-SWIFT/Classes/AppDependencies.swift b/VIPER-SWIFT/Classes/AppDependencies.swift new file mode 100755 index 0000000..49928b5 --- /dev/null +++ b/VIPER-SWIFT/Classes/AppDependencies.swift @@ -0,0 +1,58 @@ +// +// AppDependencies.swift +// VIPER TODO +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import UIKit + +class AppDependencies { + var listWireframe = ListWireframe() + + init() { + configureDependencies() + } + + func installRootViewControllerIntoWindow(window: UIWindow) { + listWireframe.presentListInterfaceFromWindow(window) + } + + func configureDependencies() { + let coreDataStore = CoreDataStore() + let clock = DeviceClock() + let rootWireframe = RootWireframe() + + let listPresenter = ListPresenter() + let listDataManager = ListDataManager() + let listInteractor = ListInteractor(dataManager: listDataManager, clock: clock) + + let addWireframe = AddWireframe() + let addInteractor = AddInteractor() + let addPresenter = AddPresenter() + let addDataManager = AddDataManager() + + listInteractor.output = listPresenter + + listPresenter.listInteractor = listInteractor + listPresenter.listWireframe = listWireframe + + listWireframe.addWireframe = addWireframe + listWireframe.listPresenter = listPresenter + listWireframe.rootWireframe = rootWireframe + + listDataManager.coreDataStore = coreDataStore + + addInteractor.addDataManager = addDataManager + + addWireframe.addPresenter = addPresenter + + addPresenter.addWireframe = addWireframe + addPresenter.addModuleDelegate = listPresenter + addPresenter.addInteractor = addInteractor + + addDataManager.dataStore = coreDataStore + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Common/Categories/NSCalendar+CalendarAdditions.swift b/VIPER-SWIFT/Classes/Common/Categories/NSCalendar+CalendarAdditions.swift new file mode 100755 index 0000000..316fd4c --- /dev/null +++ b/VIPER-SWIFT/Classes/Common/Categories/NSCalendar+CalendarAdditions.swift @@ -0,0 +1,163 @@ +// +// NSCalendar+CalendarAdditions.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +extension NSCalendar { + class func gregorianCalendar() -> NSCalendar { + return NSCalendar(calendarIdentifier: NSGregorianCalendar) + } + + func dateWithYear(year: Int, month: Int, day: Int) -> NSDate { + let components = NSDateComponents() + components.year = year + components.month = month + components.day = day + components.hour = 12 + return dateFromComponents(components) + } + + func dateForTomorrowRelativeToToday(today: NSDate) -> NSDate { + let tomorrowComponents = NSDateComponents() + tomorrowComponents.day = 1 + return dateByAddingComponents(tomorrowComponents, toDate: today, options: nil) + } + + func dateForEndOfWeekWithDate(date: NSDate) -> NSDate { + let daysRemainingThisWeek = daysRemainingInWeekWithDate(date) + let remainingDaysComponent = NSDateComponents() + remainingDaysComponent.day = daysRemainingThisWeek + return dateByAddingComponents(remainingDaysComponent, toDate: date, options: nil) + } + + func dateForBeginningOfDay(date: NSDate) -> NSDate { + let newComponent = components((NSCalendarUnit.YearCalendarUnit | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay), fromDate: date) + let newDate = dateFromComponents(newComponent) + return newDate + } + + func dateForEndOfDay(date: NSDate) -> NSDate { + let components = NSDateComponents() + components.day = 1 + let toDate = dateForBeginningOfDay(date) + let nextDay = dateByAddingComponents(components, toDate: toDate, options: nil) + let endDay = nextDay.dateByAddingTimeInterval(-1) + return nextDay + } + + func daysRemainingInWeekWithDate(date: NSDate) -> Int { + let weekdayComponent = components(NSCalendarUnit.WeekdayCalendarUnit, fromDate: date) + let daysRange = rangeOfUnit(NSCalendarUnit.WeekdayCalendarUnit, inUnit: NSCalendarUnit.WeekCalendarUnit, forDate: date) + let daysPerWeek = daysRange.length + let daysRemaining = daysPerWeek - weekdayComponent.weekday + return daysRemaining + } + + func dateForEndOfFollowingWeekWithDate(date: NSDate) -> NSDate { + let endOfWeek = dateForEndOfWeekWithDate(date) + let nextWeekComponent = NSDateComponents() + nextWeekComponent.setWeek(1) + let followingWeekDate = dateByAddingComponents(nextWeekComponent, toDate: endOfWeek, options: nil) + return followingWeekDate + } + + func isDate(date: NSDate, beforeYearMonthDay: NSDate) -> Bool { + let comparison = compareYearMonthDay(date, toYearMonthDay: beforeYearMonthDay) + let result = comparison == NSComparisonResult.OrderedAscending + return result + } + + func isDate(date: NSDate, equalToYearMonthDay: NSDate) -> Bool { + let comparison = compareYearMonthDay(date, toYearMonthDay: equalToYearMonthDay) + let result = comparison == NSComparisonResult.OrderedSame + return result + } + + func isDate(date: NSDate, duringSameWeekAsDate: NSDate) -> Bool { + let dateComponents = components(NSCalendarUnit.WeekCalendarUnit, fromDate: date) + let duringSameWeekComponents = components(NSCalendarUnit.WeekCalendarUnit, fromDate: duringSameWeekAsDate) + let result = dateComponents.week() == duringSameWeekComponents.week() + return result + } + + func isDate(date: NSDate, duringWeekAfterDate: NSDate) -> Bool { + let nextWeek = dateForEndOfFollowingWeekWithDate(duringWeekAfterDate) + let dateComponents = components(NSCalendarUnit.WeekCalendarUnit, fromDate: date) + let nextWeekComponents = components(NSCalendarUnit.WeekCalendarUnit, fromDate: nextWeek) + let result = dateComponents.week() == nextWeekComponents.week() + return result + } + + func compareYearMonthDay(date: NSDate, toYearMonthDay: NSDate) -> NSComparisonResult { + let dateComponents = yearMonthDayComponentsFromDate(date) + let yearMonthDayComponents = yearMonthDayComponentsFromDate(toYearMonthDay) + + var result = compareInteger(dateComponents.year, right: yearMonthDayComponents.year) + + if result == NSComparisonResult.OrderedSame { + result = compareInteger(dateComponents.month, right: yearMonthDayComponents.month) + + if result == NSComparisonResult.OrderedSame { + result = compareInteger(dateComponents.day, right: yearMonthDayComponents.day) + } + } + + return result + } + + func yearMonthDayComponentsFromDate(date: NSDate) -> NSDateComponents { + let newComponents = components((NSCalendarUnit.YearCalendarUnit | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitDay), fromDate: date) + return newComponents + } + + func compareInteger(left: Int, right: Int) -> NSComparisonResult { + var result = NSComparisonResult.OrderedDescending + + if left == right { + result = NSComparisonResult.OrderedSame + } else if left < right { + result = NSComparisonResult.OrderedAscending + } else { + result = NSComparisonResult.OrderedDescending + } + + return result + } + + func nearTermRelationForDate(date: NSDate, relativeToToday: NSDate) -> NearTermDateRelation { + var relation = NearTermDateRelation.OutOfRange + + let dateForTomorrow = dateForTomorrowRelativeToToday(relativeToToday) + + let isDateBeforeYearMonthDay = isDate(date, beforeYearMonthDay: relativeToToday) + let isDateEqualToYearMonthDay = isDate(date, equalToYearMonthDay: relativeToToday) + let isDateEqualToYearMonthDayRelativeToTomorrow = isDate(date, equalToYearMonthDay: dateForTomorrow) + let isDateDuringSameWeekAsDate = isDate(date, duringSameWeekAsDate: relativeToToday) + let isDateDuringSameWeekAfterDate = isDate(date, duringWeekAfterDate: relativeToToday) + + if isDateBeforeYearMonthDay { + relation = NearTermDateRelation.OutOfRange + } else if isDateEqualToYearMonthDay { + relation = NearTermDateRelation.Today + } else if isDateEqualToYearMonthDayRelativeToTomorrow { + let isRelativeDateDuringSameWeek = isDate(relativeToToday, duringSameWeekAsDate: date) + + if isRelativeDateDuringSameWeek { + relation = NearTermDateRelation.Tomorrow + } else { + relation = NearTermDateRelation.NextWeek + } + } else if isDateDuringSameWeekAsDate { + relation = NearTermDateRelation.LaterThisWeek + } else if isDateDuringSameWeekAfterDate { + relation = NearTermDateRelation.NextWeek + } + + return relation + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Common/Clock/Clock.swift b/VIPER-SWIFT/Classes/Common/Clock/Clock.swift new file mode 100755 index 0000000..5baa5b1 --- /dev/null +++ b/VIPER-SWIFT/Classes/Common/Clock/Clock.swift @@ -0,0 +1,13 @@ +// +// Clock.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +protocol Clock { + func today() -> NSDate +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Common/Clock/DeviceClock.swift b/VIPER-SWIFT/Classes/Common/Clock/DeviceClock.swift new file mode 100755 index 0000000..23fab5b --- /dev/null +++ b/VIPER-SWIFT/Classes/Common/Clock/DeviceClock.swift @@ -0,0 +1,15 @@ +// +// DeviceClock.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +class DeviceClock : NSObject, Clock { + func today() -> NSDate { + return NSDate() + } +} diff --git a/VIPER-SWIFT/Classes/Common/Model/NearTermDateRelation.swift b/VIPER-SWIFT/Classes/Common/Model/NearTermDateRelation.swift new file mode 100755 index 0000000..67d3997 --- /dev/null +++ b/VIPER-SWIFT/Classes/Common/Model/NearTermDateRelation.swift @@ -0,0 +1,17 @@ +// +// NearTermDateRelation.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +enum NearTermDateRelation { + case OutOfRange, + Today, + Tomorrow, + LaterThisWeek, + NextWeek +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Common/Model/TodoItem.swift b/VIPER-SWIFT/Classes/Common/Model/TodoItem.swift new file mode 100755 index 0000000..10dd517 --- /dev/null +++ b/VIPER-SWIFT/Classes/Common/Model/TodoItem.swift @@ -0,0 +1,19 @@ +// +// TodoItem.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +struct TodoItem { + let dueDate : NSDate + let name : String + + init(dueDate: NSDate, name: String) { + self.dueDate = dueDate + self.name = name + } +} diff --git a/VIPER-SWIFT/Classes/Common/Store/CoreDataStore.swift b/VIPER-SWIFT/Classes/Common/Store/CoreDataStore.swift new file mode 100755 index 0000000..0921a62 --- /dev/null +++ b/VIPER-SWIFT/Classes/Common/Store/CoreDataStore.swift @@ -0,0 +1,71 @@ +// +// CoreDataStore.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import CoreData + +extension Array { + func lastObject() -> T { + let endIndex = self.endIndex + let lastItemIndex = endIndex - 1 + + return self[lastItemIndex] + } +} + +class CoreDataStore : NSObject { + var persistentStoreCoordinator : NSPersistentStoreCoordinator? + var managedObjectModel : NSManagedObjectModel? + var managedObjectContext : NSManagedObjectContext? + + init() { + managedObjectModel = NSManagedObjectModel.mergedModelFromBundles(nil) + + persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel) + + let domains = NSSearchPathDomainMask.UserDomainMask + let directory = NSSearchPathDirectory.DocumentDirectory + + let error = NSError() + let applicationDocumentsDirectory : AnyObject = NSFileManager.defaultManager().URLsForDirectory(directory, inDomains: domains).lastObject() + let options = [NSMigratePersistentStoresAutomaticallyOption : true, NSInferMappingModelAutomaticallyOption : true] + + let storeURL = applicationDocumentsDirectory.URLByAppendingPathComponent("VIPER-SWIFT.sqlite") + + persistentStoreCoordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: "", URL: storeURL, options: options, error: nil) + + managedObjectContext = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType) + managedObjectContext!.persistentStoreCoordinator = persistentStoreCoordinator + managedObjectContext!.undoManager = nil + + super.init() + } + + func fetchEntriesWithPredicate(predicate: NSPredicate, sortDescriptors: AnyObject[], completionBlock: ((ManagedTodoItem[]) -> Void)!) { + let fetchRequest = NSFetchRequest(entityName: "TodoItem") + fetchRequest.predicate = predicate + fetchRequest.sortDescriptors = [] + + managedObjectContext?.performBlock { + let queryResults = self.managedObjectContext?.executeFetchRequest(fetchRequest, error: nil) + let managedResults = queryResults! as ManagedTodoItem[] + completionBlock(managedResults) + } + } + + func newTodoItem() -> ManagedTodoItem { + let entityDescription = NSEntityDescription.entityForName("TodoItem", inManagedObjectContext: managedObjectContext) + let newEntry = NSManagedObject(entity: entityDescription, insertIntoManagedObjectContext: managedObjectContext) as ManagedTodoItem + + return newEntry + } + + func save() { + managedObjectContext?.save(nil) + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Common/Store/Entities/ManagedTodoItem.swift b/VIPER-SWIFT/Classes/Common/Store/Entities/ManagedTodoItem.swift new file mode 100755 index 0000000..2a4325f --- /dev/null +++ b/VIPER-SWIFT/Classes/Common/Store/Entities/ManagedTodoItem.swift @@ -0,0 +1,15 @@ +// +// ManagedTodoItem.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Conrad Stoll. All rights reserved. +// + +import Foundation +import CoreData + +class ManagedTodoItem : NSManagedObject { + @NSManaged var name : NSString + @NSManaged var date : NSDate +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Common/Store/TODO.xcdatamodeld/TODO.xcdatamodel/contents b/VIPER-SWIFT/Classes/Common/Store/TODO.xcdatamodeld/TODO.xcdatamodel/contents new file mode 100755 index 0000000..b4455c4 --- /dev/null +++ b/VIPER-SWIFT/Classes/Common/Store/TODO.xcdatamodeld/TODO.xcdatamodel/contents @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Common/View/RootWireframe.swift b/VIPER-SWIFT/Classes/Common/View/RootWireframe.swift new file mode 100755 index 0000000..66e38cc --- /dev/null +++ b/VIPER-SWIFT/Classes/Common/View/RootWireframe.swift @@ -0,0 +1,22 @@ +// +// RootWireframe.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import UIKit + +class RootWireframe : NSObject { + func showRootViewController(viewController: UIViewController, inWindow: UIWindow) { + let navigationController = navigationControllerFromWindow(inWindow) + navigationController.viewControllers = [viewController] + } + + func navigationControllerFromWindow(window: UIWindow) -> UINavigationController { + let navigationController = window.rootViewController as UINavigationController + return navigationController + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/Application Logic/Interactor/AddInteractor.swift b/VIPER-SWIFT/Classes/Modules/Add/Application Logic/Interactor/AddInteractor.swift new file mode 100755 index 0000000..4830bb0 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/Application Logic/Interactor/AddInteractor.swift @@ -0,0 +1,18 @@ +// +// AddInteractor.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +class AddInteractor : NSObject { + var addDataManager : AddDataManager? + + func saveNewEntryWithName(name: NSString, dueDate: NSDate) { + let newEntry = TodoItem(dueDate: dueDate, name: name) + addDataManager?.addNewEntry(newEntry) + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/Application Logic/Manager/AddDataManager.swift b/VIPER-SWIFT/Classes/Modules/Add/Application Logic/Manager/AddDataManager.swift new file mode 100755 index 0000000..fadd6d8 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/Application Logic/Manager/AddDataManager.swift @@ -0,0 +1,21 @@ +// +// AddDataManager.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +class AddDataManager : NSObject { + var dataStore : CoreDataStore? + + func addNewEntry(entry: TodoItem) { + let newEntry = dataStore?.newTodoItem() as ManagedTodoItem + newEntry.name = entry.name + newEntry.date = entry.dueDate; + + dataStore?.save() + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/Module Interface/AddModuleDelegateInterface.swift b/VIPER-SWIFT/Classes/Modules/Add/Module Interface/AddModuleDelegateInterface.swift new file mode 100755 index 0000000..5ee6003 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/Module Interface/AddModuleDelegateInterface.swift @@ -0,0 +1,14 @@ +// +// AddModuleDelegateInterface.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +protocol AddModuleDelegate { + func addModuleDidCancelAddAction() + func addModuleDidSaveAddAction() +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/Module Interface/AddModuleInterface.swift b/VIPER-SWIFT/Classes/Modules/Add/Module Interface/AddModuleInterface.swift new file mode 100755 index 0000000..b7a16f9 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/Module Interface/AddModuleInterface.swift @@ -0,0 +1,14 @@ +// +// AddModuleInterface.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +protocol AddModuleInterface { + func cancelAddAction() + func saveAddActionWithName(name: NSString, dueDate: NSDate) +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/User Interface/Presenter/AddPresenter.swift b/VIPER-SWIFT/Classes/Modules/Add/User Interface/Presenter/AddPresenter.swift new file mode 100755 index 0000000..6ab6752 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/User Interface/Presenter/AddPresenter.swift @@ -0,0 +1,30 @@ +// +// AddPresenter.swift +// VIPER TODO +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +class AddPresenter : NSObject, AddModuleInterface { + var addInteractor : AddInteractor? + var addWireframe : AddWireframe? + var addModuleDelegate : AddModuleDelegate? + + func cancelAddAction() { + addWireframe?.dismissAddInterface() + addModuleDelegate?.addModuleDidCancelAddAction() + } + + func saveAddActionWithName(name: NSString, dueDate: NSDate) { + addInteractor?.saveNewEntryWithName(name, dueDate: dueDate); + addWireframe?.dismissAddInterface() + addModuleDelegate?.addModuleDidSaveAddAction() + } + + func configureUserInterfaceForPresentation(addViewUserInterface: AddViewInterface) { + addViewUserInterface.setMinimumDueDate(NSDate()) + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/User Interface/Transition/AddDismissalTransition.swift b/VIPER-SWIFT/Classes/Modules/Add/User Interface/Transition/AddDismissalTransition.swift new file mode 100755 index 0000000..81ba22a --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/User Interface/Transition/AddDismissalTransition.swift @@ -0,0 +1,40 @@ +// +// AddDismissalTransition.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import UIKit + +class AddDismissalTransition : NSObject, UIViewControllerAnimatedTransitioning { + func transitionDuration(transitionContext: UIViewControllerContextTransitioning!) -> NSTimeInterval { + return 0.72 + } + + func animateTransition(transitionContext: UIViewControllerContextTransitioning!) { + let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) as AddViewController + + let finalCenter = CGPointMake(160.0, (fromVC.view.bounds.size.height / 2) - 1000.0) + + let options = UIViewAnimationOptions.CurveEaseIn + + UIView.animateWithDuration(self.transitionDuration(transitionContext), + delay: 0.0, + usingSpringWithDamping: 0.64, + initialSpringVelocity: 0.22, + options: options, + animations: { + fromVC.view.center = finalCenter + fromVC.transitioningBackgroundView.alpha = 0.0 + }, + completion: { finished in + fromVC.view.removeFromSuperview() + transitionContext.completeTransition(true) + } + ) + } + +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/User Interface/Transition/AddPresentationTransition.swift b/VIPER-SWIFT/Classes/Modules/Add/User Interface/Transition/AddPresentationTransition.swift new file mode 100755 index 0000000..88a7205 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/User Interface/Transition/AddPresentationTransition.swift @@ -0,0 +1,53 @@ +// +// AddPresentationTransition.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import UIKit + +class AddPresentationTransition: NSObject, UIViewControllerAnimatedTransitioning { + func transitionDuration(transitionContext: UIViewControllerContextTransitioning!) -> NSTimeInterval { + return 0.72 + } + + func animateTransition(transitionContext: UIViewControllerContextTransitioning!) { + let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey) + let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey) as AddViewController + + toVC.transitioningBackgroundView.backgroundColor = UIColor.darkGrayColor() + toVC.transitioningBackgroundView.alpha = 0.0 + toVC.transitioningBackgroundView.frame = UIScreen.mainScreen().bounds + + let containerView = transitionContext.containerView() + containerView.addSubview(toVC.transitioningBackgroundView) + containerView.addSubview(toVC.view) + + let toViewFrame = CGRectMake(0, 0, 260, 300) + toVC.view.frame = toViewFrame + + let finalCenter = CGPointMake(fromVC.view.bounds.size.width / 2, 20 + toViewFrame.size.height / 2) + toVC.view.center = CGPointMake(finalCenter.x, finalCenter.y - 1000) + + let options = UIViewAnimationOptions.CurveEaseIn + + UIView.animateWithDuration(self.transitionDuration(transitionContext), + delay: 0.0, + usingSpringWithDamping: 0.64, + initialSpringVelocity: 0.22, + options: options, + animations: { + toVC.view.center = finalCenter + toVC.transitioningBackgroundView.alpha = 0.7 + }, + completion: { finished in + toVC.view.center = finalCenter + transitionContext.completeTransition(true) + } + ) + } + +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/User Interface/View/AddViewController.swift b/VIPER-SWIFT/Classes/Modules/Add/User Interface/View/AddViewController.swift new file mode 100755 index 0000000..ec50fdc --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/User Interface/View/AddViewController.swift @@ -0,0 +1,78 @@ +// +// AddViewController.swift +// VIPER TODO +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import UIKit + +class AddViewController: UIViewController, UITextFieldDelegate, AddViewInterface { + var eventHandler : AddModuleInterface? + + @IBOutlet var nameTextField : UITextField + @IBOutlet var datePicker : UIDatePicker? + + var minimumDate : NSDate = NSDate() + var transitioningBackgroundView : UIView = UIView() + + @IBAction func save(sender: AnyObject) { + eventHandler?.saveAddActionWithName(nameTextField.text, dueDate: datePicker!.date) + } + + @IBAction func cancel(sender: AnyObject) { + nameTextField.resignFirstResponder() + eventHandler?.cancelAddAction() + } + + override func viewDidAppear(animated: Bool) { + super.viewDidAppear(animated) + + var gestureRecognizer = UITapGestureRecognizer() + gestureRecognizer.addTarget(self, action: Selector("dismiss")) + + transitioningBackgroundView.userInteractionEnabled = true + + nameTextField.becomeFirstResponder() + + if let realDatePicker = datePicker { + realDatePicker.minimumDate = minimumDate + } + } + + override func viewWillDisappear(animated: Bool) { + super.viewWillDisappear(animated) + + nameTextField.resignFirstResponder() + } + + func dismiss() { + eventHandler?.cancelAddAction() + } + + func setEntryName(name: NSString) { + nameTextField.text = name + } + + func setEntryDueDate(date: NSDate) { + if let realDatePicker = datePicker { + realDatePicker.minimumDate = date + } + } + + func setMinimumDueDate(date: NSDate) { + minimumDate = date + + if let realDatePicker = datePicker { + realDatePicker.minimumDate = date + } + } + + func textFieldShouldReturn(textField: UITextField!) -> Bool { + textField.resignFirstResponder() + + return true + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/User Interface/View/AddViewInterface.swift b/VIPER-SWIFT/Classes/Modules/Add/User Interface/View/AddViewInterface.swift new file mode 100755 index 0000000..3ecd131 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/User Interface/View/AddViewInterface.swift @@ -0,0 +1,15 @@ +// +// AddViewInterface.swift +// VIPER TODO +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +protocol AddViewInterface { + func setEntryName(name: NSString) + func setEntryDueDate(date: NSDate) + func setMinimumDueDate(date: NSDate) +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/Add/User Interface/Wireframe/AddWireframe.swift b/VIPER-SWIFT/Classes/Modules/Add/User Interface/Wireframe/AddWireframe.swift new file mode 100755 index 0000000..f1fd62a --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/Add/User Interface/Wireframe/AddWireframe.swift @@ -0,0 +1,54 @@ +// +// AddWireframe.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/4/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import UIKit + +let AddViewControllerIdentifier = "AddViewController" + +class AddWireframe : NSObject, UIViewControllerTransitioningDelegate { + + var addPresenter : AddPresenter? + var presentedViewController : UIViewController? + + func presentAddInterfaceFromViewController(viewController: UIViewController) { + let newViewController = addViewController() + newViewController.eventHandler = addPresenter + newViewController.modalPresentationStyle = .Custom + newViewController.transitioningDelegate = self + + addPresenter?.configureUserInterfaceForPresentation(newViewController) + + viewController.presentViewController(newViewController, animated: true, completion: nil) + + presentedViewController = newViewController + } + + func dismissAddInterface() { + presentedViewController?.dismissViewControllerAnimated(true, completion: nil) + } + + func addViewController() -> AddViewController { + let storyboard = mainStoryboard() + let addViewController: AddViewController = storyboard.instantiateViewControllerWithIdentifier(AddViewControllerIdentifier) as AddViewController + return addViewController + } + + func mainStoryboard() -> UIStoryboard { + let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()) + return storyboard + } + + func animationControllerForDismissedController(dismissed: UIViewController!) -> UIViewControllerAnimatedTransitioning! { + return AddDismissalTransition() + } + + func animationControllerForPresentedController(presented: UIViewController!, presentingController presenting: UIViewController!, sourceController source: UIViewController!) -> UIViewControllerAnimatedTransitioning! { + return AddPresentationTransition() + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/Application Logic/Interactor/ListInteractor.swift b/VIPER-SWIFT/Classes/Modules/List/Application Logic/Interactor/ListInteractor.swift new file mode 100755 index 0000000..f3b38d3 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/Application Logic/Interactor/ListInteractor.swift @@ -0,0 +1,47 @@ +// +// ListInteractor.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +class ListInteractor : NSObject, ListInteractorInput { + var output : ListInteractorOutput? + + let clock : Clock + let dataManager : ListDataManager + + init(dataManager: ListDataManager, clock: Clock) { + self.dataManager = dataManager + self.clock = clock + } + + func findUpcomingItems() { + let today = clock.today() + let endOfNextWeek = NSCalendar.currentCalendar().dateForEndOfFollowingWeekWithDate(today) + + dataManager.todoItemsBetweenStartDate(today, + endDate: endOfNextWeek, + completion: { todoItems in + let upcomingItems = self.upcomingItemsFromToDoItems(todoItems) + self.output?.foundUpcomingItems(upcomingItems) + }) + } + + func upcomingItemsFromToDoItems(todoItems: TodoItem[]) -> UpcomingItem[] { + let calendar = NSCalendar.autoupdatingCurrentCalendar() + + var upcomingItems : UpcomingItem[] = [] + + for todoItem in todoItems { + var dateRelation = calendar.nearTermRelationForDate(todoItem.dueDate, relativeToToday: clock.today()) + let upcomingItem = UpcomingItem(title: todoItem.name, dueDate: todoItem.dueDate, dateRelation: dateRelation) + upcomingItems.insert(upcomingItem, atIndex: upcomingItems.endIndex) + } + + return upcomingItems + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/Application Logic/Interactor/ListInteractorIO.swift b/VIPER-SWIFT/Classes/Modules/List/Application Logic/Interactor/ListInteractorIO.swift new file mode 100755 index 0000000..6be6403 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/Application Logic/Interactor/ListInteractorIO.swift @@ -0,0 +1,18 @@ +// +// ListInteractorIO.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + + +protocol ListInteractorInput { + func findUpcomingItems() +} + +protocol ListInteractorOutput { + func foundUpcomingItems(upcomingItems: UpcomingItem[]) +} diff --git a/VIPER-SWIFT/Classes/Modules/List/Application Logic/Interactor/UpcomingItem.swift b/VIPER-SWIFT/Classes/Modules/List/Application Logic/Interactor/UpcomingItem.swift new file mode 100755 index 0000000..01c694e --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/Application Logic/Interactor/UpcomingItem.swift @@ -0,0 +1,40 @@ +// +// UpcomingItem.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +struct UpcomingItem : Equatable { + let title : String = "" + let dueDate : NSDate = NSDate() + let dateRelation : NearTermDateRelation = NearTermDateRelation.OutOfRange + + init(title: String, dueDate: NSDate, dateRelation: NearTermDateRelation) { + self.title = title + self.dueDate = dueDate + self.dateRelation = dateRelation + } +} + +func == (leftSide: UpcomingItem, rightSide: UpcomingItem) -> Bool { + var hasEqualSections = false + hasEqualSections = rightSide.title == leftSide.title + + if hasEqualSections == false { + return false + } + + hasEqualSections = rightSide.dueDate == rightSide.dueDate + + if hasEqualSections == false { + return false + } + + hasEqualSections = rightSide.dateRelation == rightSide.dateRelation + + return hasEqualSections +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/Application Logic/Manager/ListDataManager.swift b/VIPER-SWIFT/Classes/Modules/List/Application Logic/Manager/ListDataManager.swift new file mode 100755 index 0000000..546c714 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/Application Logic/Manager/ListDataManager.swift @@ -0,0 +1,41 @@ + +// +// ListDataManager.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +class ListDataManager : NSObject { + var coreDataStore : CoreDataStore? + + func todoItemsBetweenStartDate(startDate: NSDate, endDate: NSDate, completion: ((TodoItem[]) -> Void)!) { + let calendar = NSCalendar.autoupdatingCurrentCalendar() + let beginning = calendar.dateForBeginningOfDay(startDate) + let end = calendar.dateForEndOfDay(endDate) + + let predicate = NSPredicate(format: "(date >= %@) AND (date <= %@)", beginning, end) + let sortDescriptors = [] + + coreDataStore?.fetchEntriesWithPredicate(predicate, + sortDescriptors: sortDescriptors, + completionBlock: { entries in + let todoItems = self.todoItemsFromDataStoreEntries(entries) + completion(todoItems) + }) + } + + func todoItemsFromDataStoreEntries(entries: ManagedTodoItem[]) -> TodoItem[] { + var todoItems : TodoItem[] = [] + + for managedTodoItem in entries { + let todoItem = TodoItem(dueDate: managedTodoItem.date, name: managedTodoItem.name) + todoItems.append(todoItem) + } + + return todoItems + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/Module Interface/ListModuleInterface.swift b/VIPER-SWIFT/Classes/Modules/List/Module Interface/ListModuleInterface.swift new file mode 100755 index 0000000..3405776 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/Module Interface/ListModuleInterface.swift @@ -0,0 +1,14 @@ +// +// ListModuleInterface.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +protocol ListModuleInterface { + func addNewEntry() + func updateView() +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/ListPresenter.swift b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/ListPresenter.swift new file mode 100755 index 0000000..bd24ab0 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/ListPresenter.swift @@ -0,0 +1,51 @@ +// +// ListPresenter.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import UIKit + +class ListPresenter : NSObject, ListInteractorOutput, ListModuleInterface, AddModuleDelegate { + var listInteractor : ListInteractorInput? + var listWireframe : ListWireframe? + var userInterface : ListViewInterface? + + func updateView() { + listInteractor?.findUpcomingItems() + } + + func foundUpcomingItems(upcomingItems: UpcomingItem[]) { + if upcomingItems.count == 0 { + userInterface?.showNoContentMessage() + } else { + updateUserInterfaceWithUpcomingItems(upcomingItems) + } + } + + func updateUserInterfaceWithUpcomingItems(upcomingItems: UpcomingItem[]) { + let upcomingDisplayData = upcomingDisplayDataWithItems(upcomingItems) + userInterface?.showUpcomingDisplayData(upcomingDisplayData) + } + + func upcomingDisplayDataWithItems(upcomingItems: UpcomingItem[]) -> UpcomingDisplayData { + let collection = UpcomingDisplayDataCollection() + collection.addUpcomingItems(upcomingItems) + return collection.collectedDisplayData() + } + + func addNewEntry() { + listWireframe?.presentAddInterface() + } + + func addModuleDidCancelAddAction() { + // No action necessary + } + + func addModuleDidSaveAddAction() { + updateView() + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplayData.swift b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplayData.swift new file mode 100755 index 0000000..9c0a93b --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplayData.swift @@ -0,0 +1,24 @@ +// +// UpcomingDisplayData.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +struct UpcomingDisplayData : Equatable { + let sections : UpcomingDisplaySection[] = [] + + init(sections: UpcomingDisplaySection[]) { + self.sections = sections + self.sections.unshare() + } +} + +func == (leftSide: UpcomingDisplayData, rightSide: UpcomingDisplayData) -> Bool { + var hasEqualSections = false + hasEqualSections = rightSide.sections == leftSide.sections + return hasEqualSections +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplayDataCollection.swift b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplayDataCollection.swift new file mode 100755 index 0000000..d152667 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplayDataCollection.swift @@ -0,0 +1,122 @@ +// +// UpcomingDisplayDataCollection.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +class UpcomingDisplayDataCollection { + let dayFormatter = NSDateFormatter() + var sections : Dictionary = Dictionary() + + init() { + dayFormatter.dateFormat = NSDateFormatter.dateFormatFromTemplate("EEEE", options: 0, locale: NSLocale.autoupdatingCurrentLocale()) + } + + func addUpcomingItems(upcomingItems: UpcomingItem[]) { + for upcomingItem in upcomingItems { + addUpcomingItem(upcomingItem) + } + } + + func addUpcomingItem(upcomingItem: UpcomingItem) { + var displayItem = displayItemForUpcomingItem(upcomingItem) + addDisplayItem(displayItem, dateRelation: upcomingItem.dateRelation) + } + + func addDisplayItem(displayItem: UpcomingDisplayItem, dateRelation: NearTermDateRelation) { + if var realSection : UpcomingDisplayItem[] = sections[dateRelation] { + realSection.append(displayItem) + sections[dateRelation] = realSection + } else { + var newSection : UpcomingDisplayItem[] = [] + newSection.append(displayItem) + sections[dateRelation] = newSection + } + } + + func displayItemForUpcomingItem(upcomingItem: UpcomingItem) -> UpcomingDisplayItem { + let day = formattedDay(upcomingItem.dueDate, dateRelation: upcomingItem.dateRelation) + let displayItem = UpcomingDisplayItem(title: upcomingItem.title, dueDate: day) + return displayItem + } + + func formattedDay(date: NSDate, dateRelation: NearTermDateRelation) -> String { + if dateRelation == NearTermDateRelation.Today { + return "" + } + + return dayFormatter.stringFromDate(date) + } + + func collectedDisplayData() -> UpcomingDisplayData { + let collectedSections : UpcomingDisplaySection[] = sortedUpcomingDisplaySections() + return UpcomingDisplayData(sections: collectedSections) + } + + func displaySectionForDateRelation(dateRelation: NearTermDateRelation) -> UpcomingDisplaySection { + let sectionTitle = sectionTitleForDateRelation(dateRelation) + let imageName = sectionImageNameForDateRelation(dateRelation) + let items = sections[dateRelation] + + return UpcomingDisplaySection(name: sectionTitle, imageName: imageName, items: items) + } + + func sortedUpcomingDisplaySections() -> UpcomingDisplaySection[] { + let keys = sortedNearTermDateRelations() + var displaySections : UpcomingDisplaySection[] = [] + + for dateRelation in keys { + var itemArray = sections[dateRelation] + + if itemArray { + var displaySection = displaySectionForDateRelation(dateRelation) + displaySections.insert(displaySection, atIndex: displaySections.endIndex) + } + } + + return displaySections + } + + func sortedNearTermDateRelations() -> NearTermDateRelation[] { + var array : NearTermDateRelation[] = [] + array.insert(NearTermDateRelation.Today, atIndex: 0) + array.insert(NearTermDateRelation.Tomorrow, atIndex: 1) + array.insert(NearTermDateRelation.LaterThisWeek, atIndex: 2) + array.insert(NearTermDateRelation.NextWeek, atIndex: 3) + return array + } + + func sectionTitleForDateRelation(dateRelation: NearTermDateRelation) -> String { + switch dateRelation { + case .Today: + return "Today" + case .Tomorrow: + return "Tomorrow" + case .LaterThisWeek: + return "Later This Week" + case .NextWeek: + return "Next Week" + case .OutOfRange: + return "Unknown" + } + } + + func sectionImageNameForDateRelation(dateRelation: NearTermDateRelation) -> String { + switch dateRelation { + case .Today: + return "check" + case .Tomorrow: + return "alarm" + case .LaterThisWeek: + return "circle" + case .NextWeek: + return "calendar" + case .OutOfRange: + return "paper" + } + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplayItem.swift b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplayItem.swift new file mode 100755 index 0000000..ac3ec88 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplayItem.swift @@ -0,0 +1,36 @@ +// +// UpcomingDisplayItem.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +struct UpcomingDisplayItem : Equatable, Printable { + let title : String = "" + let dueDate : String = "" + + var description : String { get { + return "\(title) -- \(dueDate)" + }} + + init(title: String, dueDate: String) { + self.title = title + self.dueDate = dueDate + } +} + +func == (leftSide: UpcomingDisplayItem, rightSide: UpcomingDisplayItem) -> Bool { + var hasEqualSections = false + hasEqualSections = rightSide.title == leftSide.title + + if hasEqualSections == false { + return false + } + + hasEqualSections = rightSide.dueDate == rightSide.dueDate + + return hasEqualSections +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplaySection.swift b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplaySection.swift new file mode 100755 index 0000000..5164a31 --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/User Interface/Presenter/UpcomingDisplaySection.swift @@ -0,0 +1,32 @@ + +// +// UpcomingDisplaySection.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +struct UpcomingDisplaySection : Equatable { + let name : String = "" + let imageName : String = "" + var items : UpcomingDisplayItem[] = [] + + init(name: String, imageName: String, items: UpcomingDisplayItem[]?) { + self.name = name + self.imageName = imageName + + if items { + self.items = items! + self.items.unshare() + } + } +} + +func == (leftSide: UpcomingDisplaySection, rightSide: UpcomingDisplaySection) -> Bool { + var hasEqualSections = false + hasEqualSections = rightSide.items == leftSide.items + return hasEqualSections +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/User Interface/View/ListViewController.swift b/VIPER-SWIFT/Classes/Modules/List/User Interface/View/ListViewController.swift new file mode 100755 index 0000000..954c4bd --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/User Interface/View/ListViewController.swift @@ -0,0 +1,94 @@ +// +// ListViewController.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import UIKit + +var ListEntryCellIdentifier = "ListEntryCell" + +class ListViewController : UITableViewController, ListViewInterface { + var eventHandler : ListModuleInterface? + var dataProperty : UpcomingDisplayData? + var strongTableView : UITableView? + + @IBOutlet var noContentView : UIView + + override func viewDidLoad() { + super.viewDidLoad() + + strongTableView = tableView + configureView() + } + + override func viewWillAppear(animated: Bool) { + super.viewWillAppear(animated) + + eventHandler?.updateView() + } + + func configureView() { + navigationItem.title = "VIPER TODO" + + let addItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Add, target: self, action: Selector("didTapAddButton")) + + navigationItem.rightBarButtonItem = addItem + } + + func didTapAddButton () { + eventHandler?.addNewEntry() + } + + func showNoContentMessage() { + view = noContentView + } + + func showUpcomingDisplayData(data: UpcomingDisplayData) { + view = strongTableView + + dataProperty = data + reloadEntries() + } + + func reloadEntries() { + tableView.reloadData() + } + + override func numberOfSectionsInTableView(tableView: UITableView!) -> Int { + var numberOfSections = dataProperty?.sections.count + + if dataProperty?.sections.count == nil { + numberOfSections = 0 + } + + return numberOfSections! + } + + override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { + let upcomingSection = dataProperty?.sections[section] + return upcomingSection!.items.count + } + + override func tableView(tableView: UITableView!, titleForHeaderInSection section: Int) -> String! { + let upcomingSection = dataProperty?.sections[section] + return upcomingSection!.name + } + + override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { + let upcomingSection = dataProperty?.sections[indexPath.section] + let upcomingItem = upcomingSection!.items[indexPath.row] + + let cell = tableView.dequeueReusableCellWithIdentifier(ListEntryCellIdentifier, forIndexPath: indexPath) as UITableViewCell + + cell.textLabel.text = upcomingItem.title; + cell.detailTextLabel.text = upcomingItem.dueDate; + cell.imageView.image = UIImage(named: upcomingSection!.imageName) + cell.selectionStyle = UITableViewCellSelectionStyle.None; + + return cell + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Classes/Modules/List/User Interface/View/ListViewInterface.swift b/VIPER-SWIFT/Classes/Modules/List/User Interface/View/ListViewInterface.swift new file mode 100755 index 0000000..bde4feb --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/User Interface/View/ListViewInterface.swift @@ -0,0 +1,17 @@ +// +// ListViewInterface.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation + +protocol ListViewInterface { + func showNoContentMessage() + func showUpcomingDisplayData(data: UpcomingDisplayData) + func reloadEntries () +} + + diff --git a/VIPER-SWIFT/Classes/Modules/List/User Interface/Wireframe/ListWireframe.swift b/VIPER-SWIFT/Classes/Modules/List/User Interface/Wireframe/ListWireframe.swift new file mode 100755 index 0000000..1cdbc9c --- /dev/null +++ b/VIPER-SWIFT/Classes/Modules/List/User Interface/Wireframe/ListWireframe.swift @@ -0,0 +1,43 @@ +// +// ListWireframe.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/5/14. +// Copyright (c) 2014 Mutual Mobile. All rights reserved. +// + +import Foundation +import UIKit + +let ListViewControllerIdentifier = "ListViewController" + +class ListWireframe : NSObject { + var addWireframe : AddWireframe? + var listPresenter : ListPresenter? + var rootWireframe : RootWireframe? + var listViewController : ListViewController? + + func presentListInterfaceFromWindow(window: UIWindow) { + let viewController = listViewControllerFromStoryboard() + viewController.eventHandler = listPresenter + listViewController = viewController + listPresenter!.userInterface = viewController + rootWireframe?.showRootViewController(viewController, inWindow: window) + } + + func presentAddInterface() { + addWireframe?.presentAddInterfaceFromViewController(listViewController!) + } + + func listViewControllerFromStoryboard() -> ListViewController { + let storyboard = mainStoryboard() + let viewController = storyboard.instantiateViewControllerWithIdentifier(ListViewControllerIdentifier) as ListViewController + return viewController + } + + func mainStoryboard() -> UIStoryboard { + let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()) + return storyboard + } + +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/AppIcon.appiconset/Contents.json b/VIPER-SWIFT/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100755 index 0000000..a5300b9 --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,24 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon@2x.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/AppIcon.appiconset/Icon@2x.png b/VIPER-SWIFT/Images.xcassets/AppIcon.appiconset/Icon@2x.png new file mode 100755 index 0000000..9fea245 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/AppIcon.appiconset/Icon@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/Contents.json b/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/Contents.json new file mode 100755 index 0000000..eed6cdf --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,39 @@ +{ + "images" : [ + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "filename" : "Splash-4@2x.png", + "scale" : "2x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "retina4", + "filename" : "LaunchImage@2x.png", + "minimum-system-version" : "7.0", + "orientation" : "portrait", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "filename" : "Splash-4.png", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "extent" : "full-screen", + "subtype" : "retina4", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/LaunchImage@2x.png b/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/LaunchImage@2x.png new file mode 100755 index 0000000..cc7c2a2 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/LaunchImage@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/Splash-4.png b/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/Splash-4.png new file mode 100755 index 0000000..cf08c0e Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/Splash-4.png differ diff --git a/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/Splash-4@2x.png b/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/Splash-4@2x.png new file mode 100755 index 0000000..9effa13 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/LaunchImage.launchimage/Splash-4@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/alarm.imageset/Contents.json b/VIPER-SWIFT/Images.xcassets/alarm.imageset/Contents.json new file mode 100755 index 0000000..e429f2c --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/alarm.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "alarm.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "alarm@2x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/alarm.imageset/alarm.png b/VIPER-SWIFT/Images.xcassets/alarm.imageset/alarm.png new file mode 100755 index 0000000..8341c9c Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/alarm.imageset/alarm.png differ diff --git a/VIPER-SWIFT/Images.xcassets/alarm.imageset/alarm@2x.png b/VIPER-SWIFT/Images.xcassets/alarm.imageset/alarm@2x.png new file mode 100755 index 0000000..c756b2f Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/alarm.imageset/alarm@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/calendar.imageset/Contents.json b/VIPER-SWIFT/Images.xcassets/calendar.imageset/Contents.json new file mode 100755 index 0000000..3ddcf20 --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/calendar.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "calendar.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "calendar@2x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/calendar.imageset/calendar.png b/VIPER-SWIFT/Images.xcassets/calendar.imageset/calendar.png new file mode 100755 index 0000000..c9c2d81 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/calendar.imageset/calendar.png differ diff --git a/VIPER-SWIFT/Images.xcassets/calendar.imageset/calendar@2x.png b/VIPER-SWIFT/Images.xcassets/calendar.imageset/calendar@2x.png new file mode 100755 index 0000000..0fc0781 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/calendar.imageset/calendar@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/check.imageset/Contents.json b/VIPER-SWIFT/Images.xcassets/check.imageset/Contents.json new file mode 100755 index 0000000..52258d8 --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/check.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "check.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "check@2x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/check.imageset/check.png b/VIPER-SWIFT/Images.xcassets/check.imageset/check.png new file mode 100755 index 0000000..0232412 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/check.imageset/check.png differ diff --git a/VIPER-SWIFT/Images.xcassets/check.imageset/check@2x.png b/VIPER-SWIFT/Images.xcassets/check.imageset/check@2x.png new file mode 100755 index 0000000..79fd0c5 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/check.imageset/check@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/circle.imageset/Contents.json b/VIPER-SWIFT/Images.xcassets/circle.imageset/Contents.json new file mode 100755 index 0000000..0f4d7fc --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/circle.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "circle.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "circle@2x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/circle.imageset/circle.png b/VIPER-SWIFT/Images.xcassets/circle.imageset/circle.png new file mode 100755 index 0000000..93830d9 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/circle.imageset/circle.png differ diff --git a/VIPER-SWIFT/Images.xcassets/circle.imageset/circle@2x.png b/VIPER-SWIFT/Images.xcassets/circle.imageset/circle@2x.png new file mode 100755 index 0000000..c7dd443 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/circle.imageset/circle@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/empty.imageset/Contents.json b/VIPER-SWIFT/Images.xcassets/empty.imageset/Contents.json new file mode 100755 index 0000000..26eb90f --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/empty.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "empty.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "empty@2x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/empty.imageset/empty.png b/VIPER-SWIFT/Images.xcassets/empty.imageset/empty.png new file mode 100755 index 0000000..c500e97 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/empty.imageset/empty.png differ diff --git a/VIPER-SWIFT/Images.xcassets/empty.imageset/empty@2x.png b/VIPER-SWIFT/Images.xcassets/empty.imageset/empty@2x.png new file mode 100755 index 0000000..05d923e Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/empty.imageset/empty@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/line.imageset/Contents.json b/VIPER-SWIFT/Images.xcassets/line.imageset/Contents.json new file mode 100755 index 0000000..91cfff1 --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/line.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "line.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "line@2x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/line.imageset/line.png b/VIPER-SWIFT/Images.xcassets/line.imageset/line.png new file mode 100755 index 0000000..e74c393 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/line.imageset/line.png differ diff --git a/VIPER-SWIFT/Images.xcassets/line.imageset/line@2x.png b/VIPER-SWIFT/Images.xcassets/line.imageset/line@2x.png new file mode 100755 index 0000000..4cae37b Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/line.imageset/line@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/month.imageset/Contents.json b/VIPER-SWIFT/Images.xcassets/month.imageset/Contents.json new file mode 100755 index 0000000..ff84a3a --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/month.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "month.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "month@2x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/month.imageset/month.png b/VIPER-SWIFT/Images.xcassets/month.imageset/month.png new file mode 100755 index 0000000..4c19c7e Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/month.imageset/month.png differ diff --git a/VIPER-SWIFT/Images.xcassets/month.imageset/month@2x.png b/VIPER-SWIFT/Images.xcassets/month.imageset/month@2x.png new file mode 100755 index 0000000..b98c425 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/month.imageset/month@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/notes.imageset/Contents.json b/VIPER-SWIFT/Images.xcassets/notes.imageset/Contents.json new file mode 100755 index 0000000..312f2a4 --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/notes.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "notes.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "notes@2x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/notes.imageset/notes.png b/VIPER-SWIFT/Images.xcassets/notes.imageset/notes.png new file mode 100755 index 0000000..2f95c72 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/notes.imageset/notes.png differ diff --git a/VIPER-SWIFT/Images.xcassets/notes.imageset/notes@2x.png b/VIPER-SWIFT/Images.xcassets/notes.imageset/notes@2x.png new file mode 100755 index 0000000..dcd4789 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/notes.imageset/notes@2x.png differ diff --git a/VIPER-SWIFT/Images.xcassets/paper.imageset/Contents.json b/VIPER-SWIFT/Images.xcassets/paper.imageset/Contents.json new file mode 100755 index 0000000..57ddab2 --- /dev/null +++ b/VIPER-SWIFT/Images.xcassets/paper.imageset/Contents.json @@ -0,0 +1,18 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "paper.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "paper@2x.png" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/VIPER-SWIFT/Images.xcassets/paper.imageset/paper.png b/VIPER-SWIFT/Images.xcassets/paper.imageset/paper.png new file mode 100755 index 0000000..257ca70 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/paper.imageset/paper.png differ diff --git a/VIPER-SWIFT/Images.xcassets/paper.imageset/paper@2x.png b/VIPER-SWIFT/Images.xcassets/paper.imageset/paper@2x.png new file mode 100755 index 0000000..59ac513 Binary files /dev/null and b/VIPER-SWIFT/Images.xcassets/paper.imageset/paper@2x.png differ diff --git a/VIPER-SWIFT/Info.plist b/VIPER-SWIFT/Info.plist new file mode 100755 index 0000000..a37913d --- /dev/null +++ b/VIPER-SWIFT/Info.plist @@ -0,0 +1,42 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.mutualmobile.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UIStatusBarStyle + UIStatusBarStyleLightContent + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/VIPER-SWIFTTests/CalendarTests.swift b/VIPER-SWIFTTests/CalendarTests.swift new file mode 100755 index 0000000..c5295d8 --- /dev/null +++ b/VIPER-SWIFTTests/CalendarTests.swift @@ -0,0 +1,70 @@ +// +// CalendarTests.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/6/14. +// Copyright (c) 2014 Conrad Stoll. All rights reserved. +// + +import XCTest + +class CalendarTests: XCTestCase { + var calendar = NSCalendar() + + override func setUp() { + super.setUp() + + calendar = NSCalendar.gregorianCalendar() + } + + func testEarlyYearMonthDayIsBeforeLaterYearMonthDay() { + let earlyDate = calendar.dateWithYear(2004, month: 2, day: 29) + let laterDate = calendar.dateWithYear(2004, month: 3, day: 1) + let comparison = calendar.isDate(earlyDate, beforeYearMonthDay: laterDate) + XCTAssert(comparison, "\(earlyDate) should be before \(laterDate)") + } + + func testYearMonthDayIsNotBeforeSameYearMonthDay() { + let earlyDate = calendar.dateWithYear(2005, month: 6, day: 1) + let laterDate = calendar.dateWithYear(2005, month: 6, day: 1) + let comparison = calendar.isDate(earlyDate, beforeYearMonthDay: laterDate) + XCTAssertFalse(comparison, "\(earlyDate) should not be before \(laterDate)") + } + + func testLaterYearMonthDayIsNotBeforeEarlyYearMonthDay() { + let earlyDate = calendar.dateWithYear(2006, month: 4, day: 15) + let laterDate = calendar.dateWithYear(2006, month: 4, day: 16) + let comparison = calendar.isDate(laterDate, beforeYearMonthDay: earlyDate) + XCTAssertFalse(comparison, "\(earlyDate) should not be before \(laterDate)") + } + + func testEqualYearMonthDaysCompareAsEqual() { + let earlyDate = calendar.dateWithYear(2005, month: 6, day: 1) + let laterDate = calendar.dateWithYear(2005, month: 6, day: 1) + let comparison = calendar.isDate(earlyDate, equalToYearMonthDay: laterDate) + XCTAssert(comparison, "\(earlyDate) should equal \(laterDate)") + } + + func testDifferentYearMonthDaysCompareAsNotEqual() { + let earlyDate = calendar.dateWithYear(2005, month: 6, day: 1) + let laterDate = calendar.dateWithYear(2005, month: 6, day: 2) + let comparison = calendar.isDate(earlyDate, equalToYearMonthDay: laterDate) + XCTAssertFalse(comparison, "\(earlyDate) should not equal \(laterDate)") + } + + func testEndOfNextWeekDuringSameYear() { + let date = calendar.dateWithYear(2005, month: 8, day: 2) + let expectedNextWeek = calendar.dateWithYear(2005, month: 8, day: 13) + let nextWeek = calendar.dateForEndOfFollowingWeekWithDate(date) + let comparison = calendar.isDate(nextWeek, equalToYearMonthDay: expectedNextWeek) + XCTAssert(comparison, "Next week should end on \(expectedNextWeek) (not \(nextWeek))") + } + + func testEndOfNextWeekDuringFollowingYear() { + let date = calendar.dateWithYear(2005, month: 12, day: 27) + let expectedNextWeek = calendar.dateWithYear(2006, month: 1, day: 7) + let nextWeek = calendar.dateForEndOfFollowingWeekWithDate(date) + let comparison = calendar.isDate(nextWeek, equalToYearMonthDay: expectedNextWeek) + XCTAssert(comparison, "Next week should end on \(expectedNextWeek) (not \(nextWeek))") + } +} diff --git a/VIPER-SWIFTTests/DataTests.swift b/VIPER-SWIFTTests/DataTests.swift new file mode 100755 index 0000000..1bfb7d7 --- /dev/null +++ b/VIPER-SWIFTTests/DataTests.swift @@ -0,0 +1,31 @@ +// +// DataStoreTests.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/6/14. +// Copyright (c) 2014 Conrad Stoll. All rights reserved. +// + +import XCTest + +class DataTests: XCTestCase { + var dataStore = CoreDataStore() + var dataManager = ListDataManager() + + override func setUp() { + super.setUp() + + dataManager.coreDataStore = dataStore + } + + func testPerformance() { + self.measureBlock() { + let startDate = NSDate() + let endDate = NSDate(timeIntervalSinceReferenceDate: 0) + self.dataManager.todoItemsBetweenStartDate(startDate, endDate: endDate, completion: { entries in + + }) + } + } + +} diff --git a/VIPER-SWIFTTests/Info.plist b/VIPER-SWIFTTests/Info.plist new file mode 100755 index 0000000..99d9e6e --- /dev/null +++ b/VIPER-SWIFTTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.mutualmobile.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/VIPER-SWIFTTests/RelativeDateTests.swift b/VIPER-SWIFTTests/RelativeDateTests.swift new file mode 100755 index 0000000..48a20f9 --- /dev/null +++ b/VIPER-SWIFTTests/RelativeDateTests.swift @@ -0,0 +1,75 @@ +// +// RelativeDateTests.swift +// VIPER-SWIFT +// +// Created by Conrad Stoll on 6/6/14. +// Copyright (c) 2014 Conrad Stoll. All rights reserved. +// + +import XCTest + +class RelativeDateTests: XCTestCase { + var calendar = NSCalendar() + + override func setUp() { + super.setUp() + + calendar = NSCalendar.gregorianCalendar() + } + + func testDateBeforeTodayIsOutOfBounds() { + let date = calendar.dateWithYear(2000, month: 1, day: 1) + let today = calendar.dateWithYear(2000, month: 1, day: 2) + let relation = calendar.nearTermRelationForDate(date, relativeToToday: today) + XCTAssertEqual(relation, NearTermDateRelation.OutOfRange, "\(date) should be out of range.") + } + + func testTodayRelatesAsToday() { + let date = calendar.dateWithYear(2000, month: 1, day: 1) + let today = calendar.dateWithYear(2000, month: 1, day: 1) + let relation = calendar.nearTermRelationForDate(date, relativeToToday: today) + XCTAssertEqual(relation, NearTermDateRelation.Today, "\(date) should be today.") + } + + func testTomorrowDuringTheSameWeekAsTodayRelatesAsTomorrow() { + let date = calendar.dateWithYear(2004, month: 1, day: 3) + let today = calendar.dateWithYear(2004, month: 1, day: 2) + let relation = calendar.nearTermRelationForDate(date, relativeToToday: today) + XCTAssertEqual(relation, NearTermDateRelation.Tomorrow, "\(date) should be tomorrow.") + } + + func testTomorrowDuringNextWeekRelatesAsNextWeek() { + let date = calendar.dateWithYear(2004, month: 10, day: 10) + let today = calendar.dateWithYear(2004, month: 10, day: 9) + let relation = calendar.nearTermRelationForDate(date, relativeToToday: today) + XCTAssertEqual(relation, NearTermDateRelation.NextWeek, "\(date) should be next week.") + } + + func testDateAfterTomorrowButDuringTheSameWeekAsTodayRelatesAsLaterThisWeek() { + let date = calendar.dateWithYear(2004, month: 3, day: 6) + let today = calendar.dateWithYear(2004, month: 3, day: 2) + let relation = calendar.nearTermRelationForDate(date, relativeToToday: today) + XCTAssertEqual(relation, NearTermDateRelation.LaterThisWeek, "\(date) should be later this week.") + } + + func testDateDuringWeekAfterTodayRelatesAsNextWeek() { + let date = calendar.dateWithYear(2004, month: 7, day: 11) + let today = calendar.dateWithYear(2004, month: 7, day: 6) + let relation = calendar.nearTermRelationForDate(date, relativeToToday: today) + XCTAssertEqual(relation, NearTermDateRelation.NextWeek, "\(date) should be next week.") + } + + func testDateDuringWeekAfterTodayThatFallsInNextYearRelatesAsNextWeek() { + let date = calendar.dateWithYear(2006, month: 1, day: 2) + let today = calendar.dateWithYear(2005, month: 12, day: 29) + let relation = calendar.nearTermRelationForDate(date, relativeToToday: today) + XCTAssertEqual(relation, NearTermDateRelation.NextWeek, "\(date) should be next week.") + } + + func testDateBeyondNextWeekRelatesAsOutOfRange() { + let date = calendar.dateWithYear(2005, month: 9, day: 25) + let today = calendar.dateWithYear(2005, month: 9, day: 14) + let relation = calendar.nearTermRelationForDate(date, relativeToToday: today) + XCTAssertEqual(relation, NearTermDateRelation.OutOfRange, "\(date) should be next week.") + } +}