From 508c394faa7c0474fa2cf0541f743448254f5f41 Mon Sep 17 00:00:00 2001 From: John Clayton Date: Fri, 23 Aug 2019 16:12:55 -0400 Subject: [PATCH] initial import of source --- .DS_Store | Bin 0 -> 6148 bytes .modulo | 14 + Cartfile | 1 + Cartfile.resolved | 1 + Carthage/Checkouts/Bridge/.gitignore | 71 + .../Bridge/Bridge.xcodeproj/project.pbxproj | 512 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Bridge.xcscheme | 99 + .../Checkouts/Bridge/Bridge/Bridge-internal.h | 2 + Carthage/Checkouts/Bridge/Bridge/Bridge.h | 24 + Carthage/Checkouts/Bridge/Bridge/Info.plist | 24 + .../Bridge/Bridge/Internal/ObjC+Catch.h | 17 + .../Bridge/Bridge/Internal/ObjC+Catch.m | 42 + .../Checkouts/Bridge/Bridge/Internal/ObjC.h | 12 + .../Checkouts/Bridge/Bridge/Internal/ObjC.m | 12 + Carthage/Checkouts/Bridge/Bridge/ObjC.swift | 49 + .../BridgeTests/BridgeTests-Bridging-Header.h | 5 + .../Bridge/BridgeTests/BridgeTests.swift | 78 + .../Checkouts/Bridge/BridgeTests/Info.plist | 22 + .../Checkouts/Bridge/BridgeTests/Objector.h | 16 + .../Checkouts/Bridge/BridgeTests/Objector.m | 22 + Carthage/Checkouts/Bridge/LICENSE | 21 + Carthage/Checkouts/Bridge/README.md | 73 + StoryKit.xcodeproj/project.pbxproj | 1052 ++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/StoryKit.xcscheme | 99 + .../xcschemes/StoryKitTestApp.xcscheme | 91 + StoryKit/.DS_Store | Bin 0 -> 6148 bytes StoryKit/ContainingController.swift | 13 + StoryKit/Editor.swift | 99 + StoryKit/Info.plist | 24 + StoryKit/Narratable.swift | 62 + StoryKit/Performer.swift | 313 ++ StoryKit/Scene.swift | 257 ++ StoryKit/SceneController.swift | 138 + StoryKit/SceneDescriptor.swift | 147 + StoryKit/SceneDesignable.swift | 25 + StoryKit/Script.swift | 421 +++ StoryKit/Scriptable.swift | 10 + StoryKit/Stage.swift | 241 ++ StoryKit/StaticallyIdentifiable.swift | 34 + StoryKit/Story.swift | 275 ++ StoryKit/StoryKit.h | 17 + StoryKit/StoryKit.swift | 67 + StoryKit/Storyboard.swift | 130 + StoryKit/Transition.swift | 495 +++ StoryKit/UIStoryboard+StoryKit.swift | 43 + StoryKit/UIViewController+StoryKit.swift | 64 + StoryKitDemo/.DS_Store | Bin 0 -> 6148 bytes .../StoryKitDemo.xcodeproj/project.pbxproj | 787 +++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcschemes/StoryKitDemo.xcscheme | 91 + StoryKitDemo/StoryKitDemo/.DS_Store | Bin 0 -> 6148 bytes .../StoryKitDemo/App/AppDelegate.swift | 155 + StoryKitDemo/StoryKitDemo/App/Container.swift | 43 + StoryKitDemo/StoryKitDemo/App/Model.swift | 83 + StoryKitDemo/StoryKitDemo/App/State.swift | 133 + .../App/UIResponder+StoryKitDemo.swift | 16 + .../StoryKitDemo/Generated/Favorites.swift | 31 + .../StoryKitDemo/Generated/Login.swift | 23 + .../StoryKitDemo/Generated/Main.swift | 39 + .../StoryKitDemo/Generated/Photos.swift | 39 + .../StoryKitDemo/Generated/Scripts.swift | 39 + .../StoryKitDemo/Generated/Search.swift | 31 + .../StoryKitDemo/Generated/Tags.swift | 35 + StoryKitDemo/StoryKitDemo/Info.plist | 68 + StoryKitDemo/StoryKitDemo/Interface/.DS_Store | Bin 0 -> 6148 bytes .../Favorites/Base.lproj/Favorites.storyboard | 46 + .../Favorites/FavoriteViewController.swift | 33 + .../Favorites/FavoritesViewController.swift | 56 + .../Interface/Login/Login.storyboard | 64 + .../Interface/Login/LoginViewController.swift | 34 + .../Interface/Main/Base.lproj/Main.storyboard | 144 + .../Interface/Main/RootViewController.swift | 11 + .../Photos/Base.lproj/Photos.storyboard | 239 ++ .../Photos/CategoriesViewController.swift | 40 + .../Photos/CategoryPhotosViewController.swift | 78 + .../Photos/PhotoViewController.swift | 123 + .../Interface/Scripts/FormFieldCell.swift | 14 + .../Interface/Scripts/FormFieldCell.xib | 53 + .../Scripts/ScriptFormViewController.swift | 66 + .../Scripts/ScriptViewController.swift | 101 + .../Interface/Scripts/Scripts.storyboard | 241 ++ .../Scripts/ScriptsViewController.swift | 49 + .../StoryKitDemo/Interface/Search/.DS_Store | Bin 0 -> 6148 bytes .../Interface/Search/Base.lproj/.DS_Store | Bin 0 -> 6148 bytes .../Search/Base.lproj/Search.storyboard | 73 + .../Search/SearchResultsViewController.swift | 65 + .../Search/SearchViewController.swift | 75 + .../Interface/Shared/AdaptiveFlowLayout.swift | 36 + .../Shared/AutoSizingTableView.swift | 16 + .../Interface/Shared/PaddedLabel.swift | 23 + .../Shared/PhotoCollectionViewCell.swift | 22 + .../Shared/PhotoCollectionViewCell.xib | 42 + .../Interface/Shared/PhotoTableViewCell.swift | 28 + .../Interface/Shared/PhotoTableViewCell.xib | 56 + .../Interface/Shared/PhotoView.swift | 146 + .../Interface/Shared/PhotoView.xib | 55 + .../Interface/Shared/TagsView.swift | 87 + .../Interface/Shared/ViewReference.swift | 62 + .../Interface/Tags/TagViewController.swift | 56 + .../Interface/Tags/Tags.storyboard | 109 + .../Interface/Tags/TagsViewController.swift | 49 + .../AppIcon.appiconset/Contents.json | 98 + .../BarItemHeartOff@3x.png | Bin 0 -> 2516 bytes .../BarItemHeart.imageset/Contents.json | 24 + .../BarItemHeartOn@3x.png | Bin 0 -> 2043 bytes .../BarItemHeartOn.imageset/Contents.json | 24 + .../Resources/Assets.xcassets/Contents.json | 6 + .../PhotosTab.imageset/Contents.json | 24 + .../PhotosTab.imageset/PhotosTab@3x.png | Bin 0 -> 2381 bytes .../Base.lproj/LaunchScreen.storyboard | 29 + .../StoryKitDemo/StoryKit/Favorites.swift | 26 + .../StoryKitDemo/StoryKit/Login.swift | 17 + StoryKitDemo/StoryKitDemo/StoryKit/Main.swift | 22 + .../StoryKitDemo/StoryKit/Photos.swift | 32 + .../StoryKitDemo/StoryKit/Scripts.swift | 41 + .../StoryKitDemo/StoryKit/Search.swift | 26 + StoryKitDemo/StoryKitDemo/StoryKit/Tags.swift | 35 + StoryKitTestApp/AppDelegate.swift | 46 + .../AppIcon.appiconset/Contents.json | 98 + StoryKitTestApp/Assets.xcassets/Contents.json | 6 + .../first.imageset/Contents.json | 12 + .../Assets.xcassets/first.imageset/first.pdf | Bin 0 -> 2465 bytes .../second.imageset/Contents.json | 12 + .../second.imageset/second.pdf | Bin 0 -> 2423 bytes .../Base.lproj/LaunchScreen.storyboard | 25 + StoryKitTestApp/Base.lproj/Main.storyboard | 102 + StoryKitTestApp/FirstViewController.swift | 20 + StoryKitTestApp/Info.plist | 55 + StoryKitTestApp/SecondViewController.swift | 20 + StoryKitTests/Info.plist | 22 + StoryKitTests/StoryTests.swift | 36 + StoryKitTests/Storyboards.swift | 9 + StoryKitTool/.DS_Store | Bin 0 -> 6148 bytes StoryKitTool/Package.resolved | 43 + StoryKitTool/Package.swift | 30 + StoryKitTool/README.md | 3 + StoryKitTool/Sources/.DS_Store | Bin 0 -> 6148 bytes StoryKitTool/Sources/StoryKitTool/.DS_Store | Bin 0 -> 6148 bytes StoryKitTool/Sources/StoryKitTool/main.swift | 26 + .../Sources/StoryKitToolCore/.DS_Store | Bin 0 -> 6148 bytes .../Sources/StoryKitToolCore/Common.swift | 28 + .../Sources/StoryKitToolCore/Errors.swift | 36 + .../StoryKitToolCore/InitCommand.swift | 72 + .../Sources/StoryKitToolCore/Model.swift | 238 ++ .../StoryKitToolCore/StoryKitTool.swift | 81 + .../Storyboard.template.swift | 110 + .../StoryKitToolCore/StoryboardBuilder.swift | 121 + .../StoryKitToolCore/StoryboardLoader.swift | 92 + .../StoryKitToolCore/StoryboardWriter.swift | 127 + .../StoryKitToolCore/UpdateCommand.swift | 98 + .../Sources/StoryKitToolCore/Version.swift | 21 + .../StoryKitToolCore/VersionCommand.swift | 30 + .../StoryKitTool.xcodeproj/Basic_Info.plist | 25 + .../StoryKitTool.xcodeproj/CYaml_Info.plist | 25 + .../StoryKitTool.xcodeproj/Clang_C_Info.plist | 25 + .../StoryKitTool.xcodeproj/POSIX_Info.plist | 25 + .../StoryKitTool.xcodeproj/PathKit_Info.plist | 25 + .../StoryKitTool.xcodeproj/SPMLibc_Info.plist | 25 + .../SWXMLHash_Info.plist | 25 + .../SourceKit_Info.plist | 25 + .../SourceKittenFramework_Info.plist | 25 + .../StoryKitTool.xcodeproj/Stencil_Info.plist | 25 + .../StoryKitToolCoreTests_Info.plist | 25 + .../StoryKitToolCore_Info.plist | 25 + .../StoryKitToolTests_Info.plist | 25 + .../StoryKitTool.xcodeproj/Utility_Info.plist | 25 + .../StoryKitTool.xcodeproj/Yams_Info.plist | 25 + .../StoryKitTool.xcodeproj/clibc_Info.plist | 25 + .../StoryKitTool.xcodeproj/project.pbxproj | 3054 +++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Basic.xcscheme | 80 + .../xcshareddata/xcschemes/CYaml.xcscheme | 80 + .../xcshareddata/xcschemes/Clang_C.xcscheme | 80 + .../xcshareddata/xcschemes/POSIX.xcscheme | 80 + .../xcshareddata/xcschemes/PathKit.xcscheme | 80 + .../PathKitPackageDescription.xcscheme | 80 + .../xcshareddata/xcschemes/SPMLibc.xcscheme | 80 + .../xcshareddata/xcschemes/SWXMLHash.xcscheme | 80 + .../SWXMLHashPackageDescription.xcscheme | 80 + .../xcshareddata/xcschemes/SourceKit.xcscheme | 80 + .../xcschemes/SourceKittenFramework.xcscheme | 80 + .../SourceKittenPackageDescription.xcscheme | 80 + .../xcshareddata/xcschemes/Stencil.xcscheme | 80 + .../StencilPackageDescription.xcscheme | 80 + .../xcschemes/StoryKitTool-Package.xcscheme | 105 + .../xcschemes/StoryKitTool.xcscheme | 138 + .../xcschemes/StoryKitToolCore.xcscheme | 80 + .../StoryKitToolPackageDescription.xcscheme | 80 + .../StoryKitToolPackageTests.xcscheme | 80 + .../SwiftPMPackageDescription.xcscheme | 80 + .../xcshareddata/xcschemes/Utility.xcscheme | 80 + .../xcshareddata/xcschemes/Yams.xcscheme | 80 + .../xcschemes/YamsPackageDescription.xcscheme | 80 + .../xcshareddata/xcschemes/clibc.xcscheme | 80 + .../xcshareddata/xcschemes/storykit.xcscheme | 80 + StoryKitTool/Tests/.DS_Store | Bin 0 -> 6148 bytes StoryKitTool/Tests/LinuxMain.swift | 7 + .../StoryKitToolCoreTests/Fixtures/.DS_Store | Bin 0 -> 6148 bytes .../Generated/Main-Modified/Main.swift | 63 + .../Generated/Main-Modified/One.swift | 48 + .../Generated/Main-Modified/Three.swift | 39 + .../Generated/Main-Modified/Two.swift | 74 + .../Fixtures/Generated/Main-Pruned/Main.swift | 47 + .../Fixtures/Generated/Main-Pruned/One.swift | 48 + .../Fixtures/Generated/Main/Main.swift | 55 + .../Fixtures/Generated/Main/One.swift | 48 + .../Fixtures/Generated/Main/Two.swift | 74 + .../Controller/Storyboard.storyboard | 28 + .../Storyboards/Input/Storyboard.storyboard | 31 + .../Storyboards/Main-Modified/Main.storyboard | 112 + .../Storyboards/Main-Modified/One.storyboard | 46 + .../Main-Modified/Three.storyboard | 28 + .../Storyboards/Main-Modified/Two.storyboard | 144 + .../Storyboards/Main-Pruned/Main.storyboard | 56 + .../Storyboards/Main-Pruned/One.storyboard | 46 + .../Fixtures/Storyboards/Main/Main.storyboard | 84 + .../Fixtures/Storyboards/Main/One.storyboard | 46 + .../Fixtures/Storyboards/Main/Two.storyboard | 144 + .../Storyboard.storyboard | 28 + .../MissingIdentifier/Storyboard.storyboard | 28 + .../Placeholders/Referenced.storyboard | 28 + .../Storyboards/Placeholders/Root.storyboard | 64 + .../InitCommandTests.swift | 97 + .../StoryboardLoaderTests.swift | 229 ++ .../StoryboardWriterTests.swift | 259 ++ .../StoryKitToolCoreTests/TestHelper.swift | 29 + .../UpdateCommandTests.swift | 138 + .../XCTestManifests.swift | 9 + .../StoryKitToolTests/StoryKitToolTests.swift | 8 + .../StoryKitToolTests/XCTestManifests.swift | 9 + StoryKitTool/Tests/copy_fixtures.sh | 12 + TODO.md | 14 + 239 files changed, 19087 insertions(+) create mode 100644 .DS_Store create mode 100644 .modulo create mode 100644 Cartfile create mode 100644 Cartfile.resolved create mode 100644 Carthage/Checkouts/Bridge/.gitignore create mode 100644 Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.pbxproj create mode 100644 Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Carthage/Checkouts/Bridge/Bridge.xcodeproj/xcshareddata/xcschemes/Bridge.xcscheme create mode 100644 Carthage/Checkouts/Bridge/Bridge/Bridge-internal.h create mode 100644 Carthage/Checkouts/Bridge/Bridge/Bridge.h create mode 100644 Carthage/Checkouts/Bridge/Bridge/Info.plist create mode 100644 Carthage/Checkouts/Bridge/Bridge/Internal/ObjC+Catch.h create mode 100644 Carthage/Checkouts/Bridge/Bridge/Internal/ObjC+Catch.m create mode 100644 Carthage/Checkouts/Bridge/Bridge/Internal/ObjC.h create mode 100644 Carthage/Checkouts/Bridge/Bridge/Internal/ObjC.m create mode 100644 Carthage/Checkouts/Bridge/Bridge/ObjC.swift create mode 100644 Carthage/Checkouts/Bridge/BridgeTests/BridgeTests-Bridging-Header.h create mode 100644 Carthage/Checkouts/Bridge/BridgeTests/BridgeTests.swift create mode 100644 Carthage/Checkouts/Bridge/BridgeTests/Info.plist create mode 100644 Carthage/Checkouts/Bridge/BridgeTests/Objector.h create mode 100644 Carthage/Checkouts/Bridge/BridgeTests/Objector.m create mode 100644 Carthage/Checkouts/Bridge/LICENSE create mode 100644 Carthage/Checkouts/Bridge/README.md create mode 100644 StoryKit.xcodeproj/project.pbxproj create mode 100644 StoryKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 StoryKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 StoryKit.xcodeproj/xcshareddata/xcschemes/StoryKit.xcscheme create mode 100644 StoryKit.xcodeproj/xcshareddata/xcschemes/StoryKitTestApp.xcscheme create mode 100644 StoryKit/.DS_Store create mode 100644 StoryKit/ContainingController.swift create mode 100644 StoryKit/Editor.swift create mode 100644 StoryKit/Info.plist create mode 100644 StoryKit/Narratable.swift create mode 100644 StoryKit/Performer.swift create mode 100644 StoryKit/Scene.swift create mode 100644 StoryKit/SceneController.swift create mode 100644 StoryKit/SceneDescriptor.swift create mode 100644 StoryKit/SceneDesignable.swift create mode 100644 StoryKit/Script.swift create mode 100644 StoryKit/Scriptable.swift create mode 100644 StoryKit/Stage.swift create mode 100644 StoryKit/StaticallyIdentifiable.swift create mode 100644 StoryKit/Story.swift create mode 100644 StoryKit/StoryKit.h create mode 100644 StoryKit/StoryKit.swift create mode 100644 StoryKit/Storyboard.swift create mode 100644 StoryKit/Transition.swift create mode 100644 StoryKit/UIStoryboard+StoryKit.swift create mode 100644 StoryKit/UIViewController+StoryKit.swift create mode 100644 StoryKitDemo/.DS_Store create mode 100644 StoryKitDemo/StoryKitDemo.xcodeproj/project.pbxproj create mode 100644 StoryKitDemo/StoryKitDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 StoryKitDemo/StoryKitDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 StoryKitDemo/StoryKitDemo.xcodeproj/xcshareddata/xcschemes/StoryKitDemo.xcscheme create mode 100644 StoryKitDemo/StoryKitDemo/.DS_Store create mode 100644 StoryKitDemo/StoryKitDemo/App/AppDelegate.swift create mode 100644 StoryKitDemo/StoryKitDemo/App/Container.swift create mode 100644 StoryKitDemo/StoryKitDemo/App/Model.swift create mode 100644 StoryKitDemo/StoryKitDemo/App/State.swift create mode 100644 StoryKitDemo/StoryKitDemo/App/UIResponder+StoryKitDemo.swift create mode 100644 StoryKitDemo/StoryKitDemo/Generated/Favorites.swift create mode 100644 StoryKitDemo/StoryKitDemo/Generated/Login.swift create mode 100644 StoryKitDemo/StoryKitDemo/Generated/Main.swift create mode 100644 StoryKitDemo/StoryKitDemo/Generated/Photos.swift create mode 100644 StoryKitDemo/StoryKitDemo/Generated/Scripts.swift create mode 100644 StoryKitDemo/StoryKitDemo/Generated/Search.swift create mode 100644 StoryKitDemo/StoryKitDemo/Generated/Tags.swift create mode 100644 StoryKitDemo/StoryKitDemo/Info.plist create mode 100644 StoryKitDemo/StoryKitDemo/Interface/.DS_Store create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Favorites/Base.lproj/Favorites.storyboard create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Favorites/FavoriteViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Favorites/FavoritesViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Login/Login.storyboard create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Login/LoginViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Main/Base.lproj/Main.storyboard create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Main/RootViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Photos/Base.lproj/Photos.storyboard create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Photos/CategoriesViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Photos/CategoryPhotosViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Photos/PhotoViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Scripts/FormFieldCell.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Scripts/FormFieldCell.xib create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Scripts/ScriptFormViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Scripts/ScriptViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Scripts/Scripts.storyboard create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Scripts/ScriptsViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Search/.DS_Store create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Search/Base.lproj/.DS_Store create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Search/Base.lproj/Search.storyboard create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Search/SearchResultsViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Search/SearchViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/AdaptiveFlowLayout.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/AutoSizingTableView.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/PaddedLabel.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/PhotoCollectionViewCell.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/PhotoCollectionViewCell.xib create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/PhotoTableViewCell.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/PhotoTableViewCell.xib create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/PhotoView.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/PhotoView.xib create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/TagsView.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Shared/ViewReference.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Tags/TagViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Tags/Tags.storyboard create mode 100644 StoryKitDemo/StoryKitDemo/Interface/Tags/TagsViewController.swift create mode 100644 StoryKitDemo/StoryKitDemo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 StoryKitDemo/StoryKitDemo/Resources/Assets.xcassets/BarItemHeart.imageset/BarItemHeartOff@3x.png create mode 100644 StoryKitDemo/StoryKitDemo/Resources/Assets.xcassets/BarItemHeart.imageset/Contents.json create mode 100644 StoryKitDemo/StoryKitDemo/Resources/Assets.xcassets/BarItemHeartOn.imageset/BarItemHeartOn@3x.png create mode 100644 StoryKitDemo/StoryKitDemo/Resources/Assets.xcassets/BarItemHeartOn.imageset/Contents.json create mode 100644 StoryKitDemo/StoryKitDemo/Resources/Assets.xcassets/Contents.json create mode 100644 StoryKitDemo/StoryKitDemo/Resources/Assets.xcassets/PhotosTab.imageset/Contents.json create mode 100644 StoryKitDemo/StoryKitDemo/Resources/Assets.xcassets/PhotosTab.imageset/PhotosTab@3x.png create mode 100644 StoryKitDemo/StoryKitDemo/Resources/Base.lproj/LaunchScreen.storyboard create mode 100644 StoryKitDemo/StoryKitDemo/StoryKit/Favorites.swift create mode 100644 StoryKitDemo/StoryKitDemo/StoryKit/Login.swift create mode 100644 StoryKitDemo/StoryKitDemo/StoryKit/Main.swift create mode 100644 StoryKitDemo/StoryKitDemo/StoryKit/Photos.swift create mode 100644 StoryKitDemo/StoryKitDemo/StoryKit/Scripts.swift create mode 100644 StoryKitDemo/StoryKitDemo/StoryKit/Search.swift create mode 100644 StoryKitDemo/StoryKitDemo/StoryKit/Tags.swift create mode 100644 StoryKitTestApp/AppDelegate.swift create mode 100644 StoryKitTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 StoryKitTestApp/Assets.xcassets/Contents.json create mode 100644 StoryKitTestApp/Assets.xcassets/first.imageset/Contents.json create mode 100644 StoryKitTestApp/Assets.xcassets/first.imageset/first.pdf create mode 100644 StoryKitTestApp/Assets.xcassets/second.imageset/Contents.json create mode 100644 StoryKitTestApp/Assets.xcassets/second.imageset/second.pdf create mode 100644 StoryKitTestApp/Base.lproj/LaunchScreen.storyboard create mode 100644 StoryKitTestApp/Base.lproj/Main.storyboard create mode 100644 StoryKitTestApp/FirstViewController.swift create mode 100644 StoryKitTestApp/Info.plist create mode 100644 StoryKitTestApp/SecondViewController.swift create mode 100644 StoryKitTests/Info.plist create mode 100644 StoryKitTests/StoryTests.swift create mode 100644 StoryKitTests/Storyboards.swift create mode 100644 StoryKitTool/.DS_Store create mode 100644 StoryKitTool/Package.resolved create mode 100644 StoryKitTool/Package.swift create mode 100644 StoryKitTool/README.md create mode 100644 StoryKitTool/Sources/.DS_Store create mode 100644 StoryKitTool/Sources/StoryKitTool/.DS_Store create mode 100644 StoryKitTool/Sources/StoryKitTool/main.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/.DS_Store create mode 100644 StoryKitTool/Sources/StoryKitToolCore/Common.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/Errors.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/InitCommand.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/Model.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/StoryKitTool.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/Storyboard.template.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/StoryboardBuilder.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/StoryboardLoader.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/StoryboardWriter.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/UpdateCommand.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/Version.swift create mode 100644 StoryKitTool/Sources/StoryKitToolCore/VersionCommand.swift create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/Basic_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/CYaml_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/Clang_C_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/POSIX_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/PathKit_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/SPMLibc_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/SWXMLHash_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/SourceKit_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/SourceKittenFramework_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/Stencil_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/StoryKitToolCoreTests_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/StoryKitToolCore_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/StoryKitToolTests_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/Utility_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/Yams_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/clibc_Info.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/project.pbxproj create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/Basic.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/CYaml.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/Clang_C.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/POSIX.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/PathKit.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/PathKitPackageDescription.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/SPMLibc.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/SWXMLHash.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/SWXMLHashPackageDescription.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/SourceKit.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/SourceKittenFramework.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/SourceKittenPackageDescription.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/Stencil.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/StencilPackageDescription.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/StoryKitTool-Package.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/StoryKitTool.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/StoryKitToolCore.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/StoryKitToolPackageDescription.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/StoryKitToolPackageTests.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/SwiftPMPackageDescription.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/Utility.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/Yams.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/YamsPackageDescription.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/clibc.xcscheme create mode 100644 StoryKitTool/StoryKitTool.xcodeproj/xcshareddata/xcschemes/storykit.xcscheme create mode 100644 StoryKitTool/Tests/.DS_Store create mode 100644 StoryKitTool/Tests/LinuxMain.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/.DS_Store create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Generated/Main-Modified/Main.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Generated/Main-Modified/One.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Generated/Main-Modified/Three.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Generated/Main-Modified/Two.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Generated/Main-Pruned/Main.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Generated/Main-Pruned/One.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Generated/Main/Main.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Generated/Main/One.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Generated/Main/Two.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Controller/Storyboard.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Input/Storyboard.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Main-Modified/Main.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Main-Modified/One.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Main-Modified/Three.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Main-Modified/Two.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Main-Pruned/Main.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Main-Pruned/One.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Main/Main.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Main/One.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Main/Two.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Malformed/MismatchedIdentifiers/Storyboard.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Malformed/MissingIdentifier/Storyboard.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Placeholders/Referenced.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/Fixtures/Storyboards/Placeholders/Root.storyboard create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/InitCommandTests.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/StoryboardLoaderTests.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/StoryboardWriterTests.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/TestHelper.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/UpdateCommandTests.swift create mode 100644 StoryKitTool/Tests/StoryKitToolCoreTests/XCTestManifests.swift create mode 100644 StoryKitTool/Tests/StoryKitToolTests/StoryKitToolTests.swift create mode 100644 StoryKitTool/Tests/StoryKitToolTests/XCTestManifests.swift create mode 100755 StoryKitTool/Tests/copy_fixtures.sh create mode 100644 TODO.md diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..ecf0433a7325fd34d42f348fae53bdd798a4b805 GIT binary patch literal 6148 zcmeHKTZ_{`6h5vI`G0bF9 z{Y03ZwJDjCBg{y6jvcrTA*5cn-J0@N1BwB~z~9Dz__!TNfkFZ!->(-@4}a`euN8&u zbZO}enVZiXI($UavpGF?Jg47x8no-AZrW*A+@zjA>x6#bxygFyr;S<=uSLOj5Z_F0 zxM`5wWzIE9BXkgb*Six2-Fp7?6&j~*7zYW@Cvx0d4`ZKpE3^~)ZSF6V^ZqS2ZD1bl zoZT33K6Op6=NEdtvb9_=%9hzL7(L5cDj22WO24mb+Tw+)w;yz#J>T7X`RetXx9>z1 z2yR+jPD&iYd+ca1LCUt1#1W0R(8l6UP1@liJc3Q6(T4z9NG64c(U$3K(x%u9_0G3n zjcYYV<33>+9G#l4it{vqvdvZ&>%*{EpNGZLvRd|7cDz)h9Ew`}eqA(eScBC|<$_@q z%ab)YbKbmsZKJvKxc8+0^aWcH@;EHO3Gw_x?_zJ}f+q?w?N>wUDMTa0d^~7k7JEIj zTr3!7X_*mY7FVo-v0Ad&+d0MzTRF;1X7 1.0.0 diff --git a/Cartfile.resolved b/Cartfile.resolved new file mode 100644 index 0000000..e5def78 --- /dev/null +++ b/Cartfile.resolved @@ -0,0 +1 @@ +github "ImpossibleFlight/Bridge" "v1.0.0" diff --git a/Carthage/Checkouts/Bridge/.gitignore b/Carthage/Checkouts/Bridge/.gitignore new file mode 100644 index 0000000..aa8d1c6 --- /dev/null +++ b/Carthage/Checkouts/Bridge/.gitignore @@ -0,0 +1,71 @@ +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +# General +.DS_Store + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output diff --git a/Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.pbxproj b/Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.pbxproj new file mode 100644 index 0000000..310dea8 --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.pbxproj @@ -0,0 +1,512 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + A4295419213480BD00ECE976 /* Bridge.h in Headers */ = {isa = PBXBuildFile; fileRef = A4295417213480BD00ECE976 /* Bridge.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A429544F2134B07B00ECE976 /* BridgeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A429544E2134B07B00ECE976 /* BridgeTests.swift */; }; + A42954512134B07B00ECE976 /* Bridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4295414213480BD00ECE976 /* Bridge.framework */; }; + A429545A2134B0E700ECE976 /* Objector.m in Sources */ = {isa = PBXBuildFile; fileRef = A42954592134B0E700ECE976 /* Objector.m */; }; + A429545C2134B1F100ECE976 /* ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = A42954242134814200ECE976 /* ObjC.swift */; }; + A429545D2134B29C00ECE976 /* ObjC+Catch.m in Sources */ = {isa = PBXBuildFile; fileRef = A42954232134814200ECE976 /* ObjC+Catch.m */; }; + A429545E2134B29C00ECE976 /* ObjC.m in Sources */ = {isa = PBXBuildFile; fileRef = A42954202134810A00ECE976 /* ObjC.m */; }; + A42954602134B2E600ECE976 /* ObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = A429541F2134810A00ECE976 /* ObjC.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A42954612134B2ED00ECE976 /* ObjC+Catch.h in Headers */ = {isa = PBXBuildFile; fileRef = A42954252134814200ECE976 /* ObjC+Catch.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A42954632134B34400ECE976 /* Bridge-internal.h in Headers */ = {isa = PBXBuildFile; fileRef = A42954622134B34400ECE976 /* Bridge-internal.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + A42954522134B07B00ECE976 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A429540B213480BD00ECE976 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A4295413213480BD00ECE976; + remoteInfo = Bridge; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + A4295414213480BD00ECE976 /* Bridge.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Bridge.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A4295417213480BD00ECE976 /* Bridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Bridge.h; sourceTree = ""; }; + A4295418213480BD00ECE976 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A429541F2134810A00ECE976 /* ObjC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ObjC.h; sourceTree = ""; }; + A42954202134810A00ECE976 /* ObjC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ObjC.m; sourceTree = ""; }; + A42954232134814200ECE976 /* ObjC+Catch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "ObjC+Catch.m"; sourceTree = ""; }; + A42954242134814200ECE976 /* ObjC.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObjC.swift; sourceTree = ""; }; + A42954252134814200ECE976 /* ObjC+Catch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ObjC+Catch.h"; sourceTree = ""; }; + A42954292134816300ECE976 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + A429544C2134B07B00ECE976 /* BridgeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BridgeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + A429544E2134B07B00ECE976 /* BridgeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BridgeTests.swift; sourceTree = ""; }; + A42954502134B07B00ECE976 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A42954572134B0E600ECE976 /* BridgeTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "BridgeTests-Bridging-Header.h"; sourceTree = ""; }; + A42954582134B0E700ECE976 /* Objector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Objector.h; sourceTree = ""; }; + A42954592134B0E700ECE976 /* Objector.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Objector.m; sourceTree = ""; }; + A42954622134B34400ECE976 /* Bridge-internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridge-internal.h"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A4295410213480BD00ECE976 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A42954492134B07B00ECE976 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A42954512134B07B00ECE976 /* Bridge.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A429540A213480BD00ECE976 = { + isa = PBXGroup; + children = ( + A42954292134816300ECE976 /* README.md */, + A4295416213480BD00ECE976 /* Bridge */, + A429544D2134B07B00ECE976 /* BridgeTests */, + A4295415213480BD00ECE976 /* Products */, + ); + sourceTree = ""; + }; + A4295415213480BD00ECE976 /* Products */ = { + isa = PBXGroup; + children = ( + A4295414213480BD00ECE976 /* Bridge.framework */, + A429544C2134B07B00ECE976 /* BridgeTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + A4295416213480BD00ECE976 /* Bridge */ = { + isa = PBXGroup; + children = ( + A4295417213480BD00ECE976 /* Bridge.h */, + A42954622134B34400ECE976 /* Bridge-internal.h */, + A42954242134814200ECE976 /* ObjC.swift */, + A429545F2134B2A600ECE976 /* Internal */, + A4295418213480BD00ECE976 /* Info.plist */, + ); + path = Bridge; + sourceTree = ""; + }; + A429544D2134B07B00ECE976 /* BridgeTests */ = { + isa = PBXGroup; + children = ( + A429544E2134B07B00ECE976 /* BridgeTests.swift */, + A42954582134B0E700ECE976 /* Objector.h */, + A42954592134B0E700ECE976 /* Objector.m */, + A42954502134B07B00ECE976 /* Info.plist */, + A42954572134B0E600ECE976 /* BridgeTests-Bridging-Header.h */, + ); + path = BridgeTests; + sourceTree = ""; + }; + A429545F2134B2A600ECE976 /* Internal */ = { + isa = PBXGroup; + children = ( + A429541F2134810A00ECE976 /* ObjC.h */, + A42954202134810A00ECE976 /* ObjC.m */, + A42954252134814200ECE976 /* ObjC+Catch.h */, + A42954232134814200ECE976 /* ObjC+Catch.m */, + ); + path = Internal; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + A4295411213480BD00ECE976 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A42954602134B2E600ECE976 /* ObjC.h in Headers */, + A4295419213480BD00ECE976 /* Bridge.h in Headers */, + A42954632134B34400ECE976 /* Bridge-internal.h in Headers */, + A42954612134B2ED00ECE976 /* ObjC+Catch.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + A4295413213480BD00ECE976 /* Bridge */ = { + isa = PBXNativeTarget; + buildConfigurationList = A429541C213480BD00ECE976 /* Build configuration list for PBXNativeTarget "Bridge" */; + buildPhases = ( + A429540F213480BD00ECE976 /* Sources */, + A4295410213480BD00ECE976 /* Frameworks */, + A4295411213480BD00ECE976 /* Headers */, + A4295412213480BD00ECE976 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Bridge; + productName = Bridge; + productReference = A4295414213480BD00ECE976 /* Bridge.framework */; + productType = "com.apple.product-type.framework"; + }; + A429544B2134B07B00ECE976 /* BridgeTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = A42954542134B07B00ECE976 /* Build configuration list for PBXNativeTarget "BridgeTests" */; + buildPhases = ( + A42954482134B07B00ECE976 /* Sources */, + A42954492134B07B00ECE976 /* Frameworks */, + A429544A2134B07B00ECE976 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + A42954532134B07B00ECE976 /* PBXTargetDependency */, + ); + name = BridgeTests; + productName = BridgeTests; + productReference = A429544C2134B07B00ECE976 /* BridgeTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A429540B213480BD00ECE976 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0940; + LastUpgradeCheck = 0940; + ORGANIZATIONNAME = "Impossible Flight, LLC"; + TargetAttributes = { + A4295413213480BD00ECE976 = { + CreatedOnToolsVersion = 9.4.1; + LastSwiftMigration = 0940; + }; + A429544B2134B07B00ECE976 = { + CreatedOnToolsVersion = 9.4.1; + LastSwiftMigration = 0940; + }; + }; + }; + buildConfigurationList = A429540E213480BD00ECE976 /* Build configuration list for PBXProject "Bridge" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = A429540A213480BD00ECE976; + productRefGroup = A4295415213480BD00ECE976 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + A4295413213480BD00ECE976 /* Bridge */, + A429544B2134B07B00ECE976 /* BridgeTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + A4295412213480BD00ECE976 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A429544A2134B07B00ECE976 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A429540F213480BD00ECE976 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A429545C2134B1F100ECE976 /* ObjC.swift in Sources */, + A429545D2134B29C00ECE976 /* ObjC+Catch.m in Sources */, + A429545E2134B29C00ECE976 /* ObjC.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A42954482134B07B00ECE976 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A429544F2134B07B00ECE976 /* BridgeTests.swift in Sources */, + A429545A2134B0E700ECE976 /* Objector.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + A42954532134B07B00ECE976 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = A4295413213480BD00ECE976 /* Bridge */; + targetProxy = A42954522134B07B00ECE976 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + A429541A213480BD00ECE976 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + 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 = 11.4; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + A429541B213480BD00ECE976 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + 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 = 11.4; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + A429541D213480BD00ECE976 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Bridge/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.Bridge; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A429541E213480BD00ECE976 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = Bridge/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.Bridge; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + A42954552134B07B00ECE976 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + INFOPLIST_FILE = BridgeTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.BridgeTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "BridgeTests/BridgeTests-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A42954562134B07B00ECE976 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + INFOPLIST_FILE = BridgeTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.BridgeTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "BridgeTests/BridgeTests-Bridging-Header.h"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A429540E213480BD00ECE976 /* Build configuration list for PBXProject "Bridge" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A429541A213480BD00ECE976 /* Debug */, + A429541B213480BD00ECE976 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A429541C213480BD00ECE976 /* Build configuration list for PBXNativeTarget "Bridge" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A429541D213480BD00ECE976 /* Debug */, + A429541E213480BD00ECE976 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A42954542134B07B00ECE976 /* Build configuration list for PBXNativeTarget "BridgeTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A42954552134B07B00ECE976 /* Debug */, + A42954562134B07B00ECE976 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A429540B213480BD00ECE976 /* Project object */; +} diff --git a/Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..eb377f9 --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Carthage/Checkouts/Bridge/Bridge.xcodeproj/xcshareddata/xcschemes/Bridge.xcscheme b/Carthage/Checkouts/Bridge/Bridge.xcodeproj/xcshareddata/xcschemes/Bridge.xcscheme new file mode 100644 index 0000000..773ef0c --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge.xcodeproj/xcshareddata/xcschemes/Bridge.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Carthage/Checkouts/Bridge/Bridge/Bridge-internal.h b/Carthage/Checkouts/Bridge/Bridge/Bridge-internal.h new file mode 100644 index 0000000..b816b96 --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge/Bridge-internal.h @@ -0,0 +1,2 @@ +#import "ObjC.h" +#import "ObjC+Catch.h" diff --git a/Carthage/Checkouts/Bridge/Bridge/Bridge.h b/Carthage/Checkouts/Bridge/Bridge/Bridge.h new file mode 100644 index 0000000..cc772e3 --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge/Bridge.h @@ -0,0 +1,24 @@ +// +// Bridge.h +// Bridge +// +// Created by John Clayton on 8/27/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +#import + +//! Project version number for Bridge. +FOUNDATION_EXPORT double BridgeVersionNumber; + +//! Project version string for Bridge. +FOUNDATION_EXPORT const unsigned char BridgeVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + + +// Internal +// Swift frameworls expose no way to reliably access internal Obj-C without making them public. Like, just don't use these unless you really want to do some custom stuff. + +#import "Bridge-internal.h" diff --git a/Carthage/Checkouts/Bridge/Bridge/Info.plist b/Carthage/Checkouts/Bridge/Bridge/Info.plist new file mode 100644 index 0000000..1007fd9 --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC+Catch.h b/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC+Catch.h new file mode 100644 index 0000000..fcf6ee3 --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC+Catch.h @@ -0,0 +1,17 @@ +// +// ObjC-internal.h +// ObjC +// +// Created by John Clayton on 8/27/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +#import + +#import "ObjC.h" + +@interface _ObjC (Catch) + ++ (BOOL) _performThrowingErrorsForExceptions:(void(^)(void))block error:(NSError **)errorPtr NS_SWIFT_NAME(_performThrowingErrorsForExceptions(block:)); + +@end diff --git a/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC+Catch.m b/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC+Catch.m new file mode 100644 index 0000000..6282c05 --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC+Catch.m @@ -0,0 +1,42 @@ +// +// ObjC.m +// StoryKit +// +// Created by John Clayton on 8/21/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +#import "ObjC+Catch.h" +#import "ObjC.h" + +@implementation _ObjC (Catch) + ++ (BOOL) _performThrowingErrorsForExceptions:(void(^)(void))block error:(NSError **)errorPtr { + @try { + block(); + } @catch (NSException *exception) { + if (errorPtr) { + NSMutableDictionary *info = [NSMutableDictionary new]; + info[NSLocalizedDescriptionKey] = [NSString stringWithFormat:@"An exception occurred: %@",[exception name]]; + if (exception != nil) { + [info setObject:exception forKey:@"exception"]; + } + if ([exception reason]) { + [info setObject:[exception reason] forKey:@"reason"]; + } + if ([exception callStackSymbols]) { + [info setObject:[exception callStackSymbols] forKey:@"callStackSymbols"]; + } + if ([exception userInfo]) { + [info setObject:[exception userInfo] forKey:@"userInfo"]; + } + + NSError *error = [NSError errorWithDomain:@"Exception Error Domain" code:-999 userInfo:info]; + *errorPtr = error; + } + return NO; + } + return YES; +} + +@end diff --git a/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC.h b/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC.h new file mode 100644 index 0000000..d69c6be --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC.h @@ -0,0 +1,12 @@ +// +// ObjC.h +// Bridge +// +// Created by John Clayton on 8/27/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +#import + +@interface _ObjC : NSObject +@end diff --git a/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC.m b/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC.m new file mode 100644 index 0000000..f235204 --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge/Internal/ObjC.m @@ -0,0 +1,12 @@ +// +// ObjC.m +// Bridge +// +// Created by John Clayton on 8/27/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +#import "ObjC.h" + +@implementation _ObjC +@end diff --git a/Carthage/Checkouts/Bridge/Bridge/ObjC.swift b/Carthage/Checkouts/Bridge/Bridge/ObjC.swift new file mode 100644 index 0000000..315cc9e --- /dev/null +++ b/Carthage/Checkouts/Bridge/Bridge/ObjC.swift @@ -0,0 +1,49 @@ +// +// ObjC.swift +// StoryKit +// +// Created by John Clayton on 8/21/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import Foundation + +public class ObjC { + /// Runs the supplied block, catching any raised Objective-C exceptions and transforming them into errors that can be caught in Swift. + /// + /// - Parameter closure: a block that can raise Objective-C exceptions + /// - Throws: an error that wraps the underlying exception + public static func throwing(_ closure:@escaping (()throws->Void)) throws { + var e: Error? + try _ObjC._performThrowingErrorsForExceptions { + // objc blocks can't throw swift errors + do { + try closure() + } catch { + e = error + } + } + if let error = e { throw error } + } + + /// Runs the supplied block, catching any raised Objective-C exceptions and transforming them into errors that can be caught in Swift, and returns the result. + /// + /// - Parameter closure: a block that can raise Objective-C exceptions + /// - Returns: the return value from closure + /// - Throws: an error that wraps the underlying exception + public static func throwingReturn(_ closure:@escaping (()throws->T)) throws -> T { + var result: T! + var e: Error? + try _ObjC._performThrowingErrorsForExceptions { + // objc blocks can't throw swift errors + do { + result = try closure() + } catch { + e = error + } + } + if let error = e { throw error } + return result + } +} + diff --git a/Carthage/Checkouts/Bridge/BridgeTests/BridgeTests-Bridging-Header.h b/Carthage/Checkouts/Bridge/BridgeTests/BridgeTests-Bridging-Header.h new file mode 100644 index 0000000..6634746 --- /dev/null +++ b/Carthage/Checkouts/Bridge/BridgeTests/BridgeTests-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "Objector.h" diff --git a/Carthage/Checkouts/Bridge/BridgeTests/BridgeTests.swift b/Carthage/Checkouts/Bridge/BridgeTests/BridgeTests.swift new file mode 100644 index 0000000..6ca2371 --- /dev/null +++ b/Carthage/Checkouts/Bridge/BridgeTests/BridgeTests.swift @@ -0,0 +1,78 @@ +// +// BridgeTests.swift +// BridgeTests +// +// Created by John Clayton on 8/27/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import XCTest + +@testable import Bridge + +class BridgeTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testThrowingThrowsWhenExceptionRaised() { + let objector = Objector() + + var e: Error? + do { + try ObjC.throwing { objector.doSomething(true) } + } catch { + e = error + } + XCTAssertNotNil(e) + } + + func testThrowingDoesNotThrowWhenNoExceptionRaised() { + let objector = Objector() + + var e: Error? + do { + try ObjC.throwing { objector.doSomething(false) } + } catch { + e = error + } + XCTAssertNil(e) + } + + func testThrowingReturnThrowsWhenExceptionRaised() { + let objector = Objector() + + var e: Error? + var o: Any? + do { + o = try ObjC.throwingReturn { objector.findSomething(true) } + } catch { + e = error + } + XCTAssertNotNil(e) + XCTAssertNil(o) + + } + + func testThrowingReturnDoesNotThrowWhenNoExceptionRaised() { + let objector = Objector() + + var e: Error? + var o: Any? + do { + o = try ObjC.throwingReturn { objector.findSomething(false) } + } catch { + e = error + } + XCTAssertNil(e) + XCTAssertNotNil(o) + + } +} diff --git a/Carthage/Checkouts/Bridge/BridgeTests/Info.plist b/Carthage/Checkouts/Bridge/BridgeTests/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/Carthage/Checkouts/Bridge/BridgeTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Carthage/Checkouts/Bridge/BridgeTests/Objector.h b/Carthage/Checkouts/Bridge/BridgeTests/Objector.h new file mode 100644 index 0000000..0ce36b4 --- /dev/null +++ b/Carthage/Checkouts/Bridge/BridgeTests/Objector.h @@ -0,0 +1,16 @@ +// +// Objector.h +// BridgeTests +// +// Created by John Clayton on 8/27/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +#import + +@interface Objector : NSObject + +- (void) doSomething:(BOOL)raise; +- (NSString *) findSomething:(BOOL)raise; + +@end diff --git a/Carthage/Checkouts/Bridge/BridgeTests/Objector.m b/Carthage/Checkouts/Bridge/BridgeTests/Objector.m new file mode 100644 index 0000000..57f6bdf --- /dev/null +++ b/Carthage/Checkouts/Bridge/BridgeTests/Objector.m @@ -0,0 +1,22 @@ +// +// Objector.m +// BridgeTests +// +// Created by John Clayton on 8/27/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +#import "Objector.h" + +@implementation Objector + +- (void) doSomething:(BOOL)raise { + NSParameterAssert(raise == NO); +} + +- (NSString *) findSomething:(BOOL)raise { + NSParameterAssert(raise == NO); + return @"abc123"; +} + +@end diff --git a/Carthage/Checkouts/Bridge/LICENSE b/Carthage/Checkouts/Bridge/LICENSE new file mode 100644 index 0000000..5befca7 --- /dev/null +++ b/Carthage/Checkouts/Bridge/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Impossible Flight + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Carthage/Checkouts/Bridge/README.md b/Carthage/Checkouts/Bridge/README.md new file mode 100644 index 0000000..8fb34d6 --- /dev/null +++ b/Carthage/Checkouts/Bridge/README.md @@ -0,0 +1,73 @@ +# Bridge + +Bridge helps make using Objective-C code in Swift more Swift-like. + +## Installation + +### Carthage + +[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. + +You can install Carthage with [Homebrew](http://brew.sh/) using the following command: + +```bash +$ brew update +$ brew install carthage +``` + +To integrate Bridge into your Xcode project using Carthage, specify it in your `Cartfile`: + +```ogdl +github "impossibleflight/Bridge" ~> 1.0.0 +``` + +Run `carthage update` to build the framework and drag the built `Bridge.framework` into your Xcode project. + +### Manually + +If you prefer not to use either of the aforementioned dependency managers, you can integrate Bridge into your project manually. + + +## Usage + +### Exceptions +#### Transforming Obj-C exceptions into Swift errors that you can catch + +Let's say you have an Objective-C interface that includes a method like this: + +```objc +@interface MyStore : NSObject +// Note: throws an exception if object can't be found ++ (id) objectForIdentifier:(String)identifier {...} +@end +``` +Using it from Swift looks like this in cases where there is no object for the passed identifier: + +```swift +let identifier = "acb123" +let object = MyStore.object(forIdentifier: identifier) --> 💥 +``` +Your app crashes while trying to do that lookup—which is a bit unexpected based on the interface alone—and if you haven't read the docs you have no idea why. This is less than ideal; we would like to catch that situtation and be able to correct the underlying problem or at least let the user know what's happening. And we know Swift lets us catch errors of this sort, right? + +Bridge to the rescue: + +```objc +let identifier = "acb123" +do { + let object = try ObjC.throwing { MyStore.object(forIdentifier: identifier) } + // do something with your object +} catch { + // uh oh. let's handle this. +} +``` + +## Authors + +* **John Clayton** - *Initial work* - [John Clayton](https://github.com/johnclayton) + +See also the list of [contributors](https://github.com/impossibleflight/Bridge/contributors) who participated in this project. + +## License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details + diff --git a/StoryKit.xcodeproj/project.pbxproj b/StoryKit.xcodeproj/project.pbxproj new file mode 100644 index 0000000..0dec9d2 --- /dev/null +++ b/StoryKit.xcodeproj/project.pbxproj @@ -0,0 +1,1052 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + A40748C021E5255700C79B34 /* ContainingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40748BF21E5255700C79B34 /* ContainingController.swift */; }; + A40A348621528FDD005A720C /* SceneController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A40A348521528FDD005A720C /* SceneController.swift */; }; + A434B855212DE9D10038783F /* Stage.swift in Sources */ = {isa = PBXBuildFile; fileRef = A434B854212DE9D10038783F /* Stage.swift */; }; + A434B857212DE9E80038783F /* Narratable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A434B856212DE9E80038783F /* Narratable.swift */; }; + A434B85A212DEAF40038783F /* Scene.swift in Sources */ = {isa = PBXBuildFile; fileRef = A434B859212DEAF40038783F /* Scene.swift */; }; + A434B85C212DEB5D0038783F /* Story.swift in Sources */ = {isa = PBXBuildFile; fileRef = A434B85B212DEB5D0038783F /* Story.swift */; }; + A434B85E212DEB890038783F /* Storyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = A434B85D212DEB890038783F /* Storyboard.swift */; }; + A434B861212DED400038783F /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = A434B860212DED400038783F /* Transition.swift */; }; + A43D49212131AFBB0050E617 /* Script.swift in Sources */ = {isa = PBXBuildFile; fileRef = A43D49202131AFBB0050E617 /* Script.swift */; }; + A43D613A21ECB96E00993EC2 /* Storyboards.swift in Sources */ = {isa = PBXBuildFile; fileRef = A43D613921ECB96E00993EC2 /* Storyboards.swift */; }; + A43D614321ECB9CB00993EC2 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A43D614221ECB9CB00993EC2 /* AppDelegate.swift */; }; + A43D614521ECB9CB00993EC2 /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A43D614421ECB9CB00993EC2 /* FirstViewController.swift */; }; + A43D614721ECB9CB00993EC2 /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A43D614621ECB9CB00993EC2 /* SecondViewController.swift */; }; + A43D614A21ECB9CB00993EC2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A43D614821ECB9CB00993EC2 /* Main.storyboard */; }; + A43D614C21ECB9CC00993EC2 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A43D614B21ECB9CC00993EC2 /* Assets.xcassets */; }; + A43D614F21ECB9CC00993EC2 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A43D614D21ECB9CC00993EC2 /* LaunchScreen.storyboard */; }; + A43D629E21ED1BE500993EC2 /* SceneDesignable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A43D629D21ED1BE500993EC2 /* SceneDesignable.swift */; }; + A4887DE1217A787F00E160D5 /* StaticallyIdentifiable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4887DE0217A787F00E160D5 /* StaticallyIdentifiable.swift */; }; + A4A1C03721AC965E00DBD0DD /* SceneDescriptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4A1C03621AC965E00DBD0DD /* SceneDescriptor.swift */; }; + A4A1C04721AF0B3300DBD0DD /* UIViewController+StoryKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4A1C04621AF0B3300DBD0DD /* UIViewController+StoryKit.swift */; }; + A4C0999D212EF83000C3F9A7 /* Performer.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4C0999C212EF83000C3F9A7 /* Performer.swift */; }; + A4D2ABB2212321F400F2E110 /* StoryKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4D2ABA8212321F400F2E110 /* StoryKit.framework */; }; + A4D2ABB7212321F400F2E110 /* StoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4D2ABB6212321F400F2E110 /* StoryTests.swift */; }; + A4D2ABB9212321F400F2E110 /* StoryKit.h in Headers */ = {isa = PBXBuildFile; fileRef = A4D2ABAB212321F400F2E110 /* StoryKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A4D2ABC32123220B00F2E110 /* StoryKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4D2ABC22123220B00F2E110 /* StoryKit.swift */; }; + A4D5EC9021260DF700DC84E5 /* UIStoryboard+StoryKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4D5EC8F21260DF700DC84E5 /* UIStoryboard+StoryKit.swift */; }; + A4F0FEDF214845E1005C6481 /* Scriptable.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4F0FEDE214845E1005C6481 /* Scriptable.swift */; }; + A4F1311321EBDD7400050802 /* Editor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4F1311221EBDD7400050802 /* Editor.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + A4080B78217A25BB00EB2419 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A437162D21496411007099CF /* Bridge.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = A4295413213480BD00ECE976; + remoteInfo = Bridge; + }; + A437163221496411007099CF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A437162D21496411007099CF /* Bridge.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A4295414213480BD00ECE976; + remoteInfo = Bridge; + }; + A437163421496411007099CF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A437162D21496411007099CF /* Bridge.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = A429544C2134B07B00ECE976; + remoteInfo = BridgeTests; + }; + A43D615421ECBA5900993EC2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4D2AB9F212321F400F2E110 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A43D613F21ECB9CB00993EC2; + remoteInfo = StoryKitTestApp; + }; + A4CB12A021F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "SwiftPM::Basic::Product"; + remoteInfo = Basic; + }; + A4CB12A221F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "Yams::CYaml::Product"; + remoteInfo = CYaml; + }; + A4CB12A421F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "SourceKitten::Clang_C::Product"; + remoteInfo = Clang_C; + }; + A4CB12A621F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "SwiftPM::POSIX::Product"; + remoteInfo = POSIX; + }; + A4CB12A821F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "PathKit::PathKit::Product"; + remoteInfo = PathKit; + }; + A4CB12AA21F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "SwiftPM::SPMLibc::Product"; + remoteInfo = SPMLibc; + }; + A4CB12AC21F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "SWXMLHash::SWXMLHash::Product"; + remoteInfo = SWXMLHash; + }; + A4CB12AE21F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "SourceKitten::SourceKit::Product"; + remoteInfo = SourceKit; + }; + A4CB12B021F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "SourceKitten::SourceKittenFramework::Product"; + remoteInfo = SourceKittenFramework; + }; + A4CB12B221F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "Stencil::Stencil::Product"; + remoteInfo = Stencil; + }; + A4CB12B421F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "StoryKitTool::StoryKitTool::Product"; + remoteInfo = StoryKitTool; + }; + A4CB12B621F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "StoryKitTool::StoryKitToolTests::Product"; + remoteInfo = StoryKitToolTests; + }; + A4CB12B821F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "SwiftPM::Utility::Product"; + remoteInfo = Utility; + }; + A4CB12BA21F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "Yams::Yams::Product"; + remoteInfo = Yams; + }; + A4CB12BC21F61A0E00418AA4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = "SwiftPM::clibc::Product"; + remoteInfo = clibc; + }; + A4D2ABB3212321F400F2E110 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = A4D2AB9F212321F400F2E110 /* Project object */; + proxyType = 1; + remoteGlobalIDString = A4D2ABA7212321F400F2E110; + remoteInfo = Storyboard; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + A40748BF21E5255700C79B34 /* ContainingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainingController.swift; sourceTree = ""; }; + A40A348521528FDD005A720C /* SceneController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneController.swift; sourceTree = ""; }; + A40B667521E696560063F1BB /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; + A434B854212DE9D10038783F /* Stage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Stage.swift; sourceTree = ""; }; + A434B856212DE9E80038783F /* Narratable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Narratable.swift; sourceTree = ""; }; + A434B859212DEAF40038783F /* Scene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scene.swift; sourceTree = ""; }; + A434B85B212DEB5D0038783F /* Story.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Story.swift; sourceTree = ""; }; + A434B85D212DEB890038783F /* Storyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storyboard.swift; sourceTree = ""; }; + A434B860212DED400038783F /* Transition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transition.swift; sourceTree = ""; }; + A437162D21496411007099CF /* Bridge.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Bridge.xcodeproj; path = ../Bridge/Bridge.xcodeproj; sourceTree = ""; }; + A43D49202131AFBB0050E617 /* Script.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Script.swift; sourceTree = ""; }; + A43D613921ECB96E00993EC2 /* Storyboards.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Storyboards.swift; sourceTree = ""; }; + A43D614021ECB9CB00993EC2 /* StoryKitTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StoryKitTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; + A43D614221ECB9CB00993EC2 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + A43D614421ECB9CB00993EC2 /* FirstViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstViewController.swift; sourceTree = ""; }; + A43D614621ECB9CB00993EC2 /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = ""; }; + A43D614921ECB9CB00993EC2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + A43D614B21ECB9CC00993EC2 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + A43D614E21ECB9CC00993EC2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + A43D615021ECB9CC00993EC2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A43D629D21ED1BE500993EC2 /* SceneDesignable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDesignable.swift; sourceTree = ""; }; + A44D861021EA32EA0041C860 /* TODO.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = TODO.md; sourceTree = ""; }; + A44D861421EA6C700041C860 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + A4887DE0217A787F00E160D5 /* StaticallyIdentifiable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StaticallyIdentifiable.swift; sourceTree = ""; }; + A4A1C03621AC965E00DBD0DD /* SceneDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDescriptor.swift; sourceTree = ""; }; + A4A1C04621AF0B3300DBD0DD /* UIViewController+StoryKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+StoryKit.swift"; sourceTree = ""; }; + A4C0999C212EF83000C3F9A7 /* Performer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Performer.swift; sourceTree = ""; }; + A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = StoryKitTool.xcodeproj; sourceTree = ""; }; + A4D2ABA8212321F400F2E110 /* StoryKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StoryKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + A4D2ABAB212321F400F2E110 /* StoryKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StoryKit.h; sourceTree = ""; }; + A4D2ABAC212321F400F2E110 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A4D2ABB1212321F400F2E110 /* StoryKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StoryKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + A4D2ABB6212321F400F2E110 /* StoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryTests.swift; sourceTree = ""; }; + A4D2ABB8212321F400F2E110 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A4D2ABC22123220B00F2E110 /* StoryKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoryKit.swift; sourceTree = ""; }; + A4D5EC8F21260DF700DC84E5 /* UIStoryboard+StoryKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIStoryboard+StoryKit.swift"; sourceTree = ""; }; + A4F0FEDE214845E1005C6481 /* Scriptable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Scriptable.swift; sourceTree = ""; }; + A4F1311221EBDD7400050802 /* Editor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Editor.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + A437163721496493007099CF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A43D613D21ECB9CB00993EC2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A4D2ABAE212321F400F2E110 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A4D2ABB2212321F400F2E110 /* StoryKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + A429542C21349D0B00ECE976 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A40B667521E696560063F1BB /* MobileCoreServices.framework */, + A437162D21496411007099CF /* Bridge.xcodeproj */, + ); + name = Frameworks; + sourceTree = ""; + }; + A437162E21496411007099CF /* Products */ = { + isa = PBXGroup; + children = ( + A437163321496411007099CF /* Bridge.framework */, + A437163521496411007099CF /* BridgeTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + A43D614121ECB9CB00993EC2 /* StoryKitTestApp */ = { + isa = PBXGroup; + children = ( + A43D614221ECB9CB00993EC2 /* AppDelegate.swift */, + A43D614421ECB9CB00993EC2 /* FirstViewController.swift */, + A43D614621ECB9CB00993EC2 /* SecondViewController.swift */, + A43D614821ECB9CB00993EC2 /* Main.storyboard */, + A43D614B21ECB9CC00993EC2 /* Assets.xcassets */, + A43D614D21ECB9CC00993EC2 /* LaunchScreen.storyboard */, + A43D615021ECB9CC00993EC2 /* Info.plist */, + ); + path = StoryKitTestApp; + sourceTree = ""; + }; + A43D620621ECC1A900993EC2 /* StoryKitTool */ = { + isa = PBXGroup; + children = ( + A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */, + ); + path = StoryKitTool; + sourceTree = ""; + }; + A4CB126821F61A0E00418AA4 /* Products */ = { + isa = PBXGroup; + children = ( + A4CB12A121F61A0E00418AA4 /* Basic.framework */, + A4CB12A321F61A0E00418AA4 /* CYaml.framework */, + A4CB12A521F61A0E00418AA4 /* Clang_C.framework */, + A4CB12A721F61A0E00418AA4 /* POSIX.framework */, + A4CB12A921F61A0E00418AA4 /* PathKit.framework */, + A4CB12AB21F61A0E00418AA4 /* SPMLibc.framework */, + A4CB12AD21F61A0E00418AA4 /* SWXMLHash.framework */, + A4CB12AF21F61A0E00418AA4 /* SourceKit.framework */, + A4CB12B121F61A0E00418AA4 /* SourceKittenFramework.framework */, + A4CB12B321F61A0E00418AA4 /* Stencil.framework */, + A4CB12B521F61A0E00418AA4 /* StoryKitTool */, + A4CB12B721F61A0E00418AA4 /* StoryKitToolTests.xctest */, + A4CB12B921F61A0E00418AA4 /* Utility.framework */, + A4CB12BB21F61A0E00418AA4 /* Yams.framework */, + A4CB12BD21F61A0E00418AA4 /* clibc.framework */, + ); + name = Products; + sourceTree = ""; + }; + A4D2AB9E212321F400F2E110 = { + isa = PBXGroup; + children = ( + A44D861421EA6C700041C860 /* README.md */, + A44D861021EA32EA0041C860 /* TODO.md */, + A4D2ABAA212321F400F2E110 /* StoryKit */, + A4D2ABB5212321F400F2E110 /* StoryKitTests */, + A43D614121ECB9CB00993EC2 /* StoryKitTestApp */, + A43D620621ECC1A900993EC2 /* StoryKitTool */, + A4D2ABA9212321F400F2E110 /* Products */, + A429542C21349D0B00ECE976 /* Frameworks */, + ); + sourceTree = ""; + }; + A4D2ABA9212321F400F2E110 /* Products */ = { + isa = PBXGroup; + children = ( + A4D2ABA8212321F400F2E110 /* StoryKit.framework */, + A4D2ABB1212321F400F2E110 /* StoryKitTests.xctest */, + A43D614021ECB9CB00993EC2 /* StoryKitTestApp.app */, + ); + name = Products; + sourceTree = ""; + }; + A4D2ABAA212321F400F2E110 /* StoryKit */ = { + isa = PBXGroup; + children = ( + A4D2ABAB212321F400F2E110 /* StoryKit.h */, + A4D2ABAC212321F400F2E110 /* Info.plist */, + A4D2ABC22123220B00F2E110 /* StoryKit.swift */, + A434B85D212DEB890038783F /* Storyboard.swift */, + A434B856212DE9E80038783F /* Narratable.swift */, + A434B854212DE9D10038783F /* Stage.swift */, + A4C0999C212EF83000C3F9A7 /* Performer.swift */, + A4F1311221EBDD7400050802 /* Editor.swift */, + A434B860212DED400038783F /* Transition.swift */, + A4A1C03621AC965E00DBD0DD /* SceneDescriptor.swift */, + A434B859212DEAF40038783F /* Scene.swift */, + A434B85B212DEB5D0038783F /* Story.swift */, + A43D49202131AFBB0050E617 /* Script.swift */, + A4F0FEDE214845E1005C6481 /* Scriptable.swift */, + A4D5EC8F21260DF700DC84E5 /* UIStoryboard+StoryKit.swift */, + A4A1C04621AF0B3300DBD0DD /* UIViewController+StoryKit.swift */, + A40A348521528FDD005A720C /* SceneController.swift */, + A4887DE0217A787F00E160D5 /* StaticallyIdentifiable.swift */, + A40748BF21E5255700C79B34 /* ContainingController.swift */, + A43D629D21ED1BE500993EC2 /* SceneDesignable.swift */, + ); + path = StoryKit; + sourceTree = ""; + }; + A4D2ABB5212321F400F2E110 /* StoryKitTests */ = { + isa = PBXGroup; + children = ( + A43D613921ECB96E00993EC2 /* Storyboards.swift */, + A4D2ABB6212321F400F2E110 /* StoryTests.swift */, + A4D2ABB8212321F400F2E110 /* Info.plist */, + ); + path = StoryKitTests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + A4D2ABA5212321F400F2E110 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + A4D2ABB9212321F400F2E110 /* StoryKit.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + A43D613F21ECB9CB00993EC2 /* StoryKitTestApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = A43D615121ECB9CC00993EC2 /* Build configuration list for PBXNativeTarget "StoryKitTestApp" */; + buildPhases = ( + A43D613C21ECB9CB00993EC2 /* Sources */, + A43D613D21ECB9CB00993EC2 /* Frameworks */, + A43D613E21ECB9CB00993EC2 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = StoryKitTestApp; + productName = StoryKitTestApp; + productReference = A43D614021ECB9CB00993EC2 /* StoryKitTestApp.app */; + productType = "com.apple.product-type.application"; + }; + A4D2ABA7212321F400F2E110 /* StoryKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = A4D2ABBC212321F400F2E110 /* Build configuration list for PBXNativeTarget "StoryKit" */; + buildPhases = ( + A4D2ABA3212321F400F2E110 /* Sources */, + A4D2ABA5212321F400F2E110 /* Headers */, + A437163721496493007099CF /* Frameworks */, + A4D2ABA6212321F400F2E110 /* Resources */, + A42954642135784500ECE976 /* Carthage copy frameworks */, + ); + buildRules = ( + ); + dependencies = ( + A4080B79217A25BB00EB2419 /* PBXTargetDependency */, + ); + name = StoryKit; + productName = Storyboard; + productReference = A4D2ABA8212321F400F2E110 /* StoryKit.framework */; + productType = "com.apple.product-type.framework"; + }; + A4D2ABB0212321F400F2E110 /* StoryKitTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = A4D2ABBF212321F400F2E110 /* Build configuration list for PBXNativeTarget "StoryKitTests" */; + buildPhases = ( + A4D2ABAD212321F400F2E110 /* Sources */, + A4D2ABAE212321F400F2E110 /* Frameworks */, + A4D2ABAF212321F400F2E110 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + A4D2ABB4212321F400F2E110 /* PBXTargetDependency */, + A43D615521ECBA5900993EC2 /* PBXTargetDependency */, + ); + name = StoryKitTests; + productName = StoryboardTests; + productReference = A4D2ABB1212321F400F2E110 /* StoryKitTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + A4D2AB9F212321F400F2E110 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1010; + LastUpgradeCheck = 0940; + ORGANIZATIONNAME = "Impossible Flight, LLC"; + TargetAttributes = { + A43D613F21ECB9CB00993EC2 = { + CreatedOnToolsVersion = 10.1; + }; + A4D2ABA7212321F400F2E110 = { + CreatedOnToolsVersion = 9.4.1; + LastSwiftMigration = 1010; + }; + A4D2ABB0212321F400F2E110 = { + CreatedOnToolsVersion = 9.4.1; + TestTargetID = A43D613F21ECB9CB00993EC2; + }; + }; + }; + buildConfigurationList = A4D2ABA2212321F400F2E110 /* Build configuration list for PBXProject "StoryKit" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = A4D2AB9E212321F400F2E110; + productRefGroup = A4D2ABA9212321F400F2E110 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = A437162E21496411007099CF /* Products */; + ProjectRef = A437162D21496411007099CF /* Bridge.xcodeproj */; + }, + { + ProductGroup = A4CB126821F61A0E00418AA4 /* Products */; + ProjectRef = A4CB126721F61A0E00418AA4 /* StoryKitTool.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + A4D2ABA7212321F400F2E110 /* StoryKit */, + A4D2ABB0212321F400F2E110 /* StoryKitTests */, + A43D613F21ECB9CB00993EC2 /* StoryKitTestApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + A437163321496411007099CF /* Bridge.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Bridge.framework; + remoteRef = A437163221496411007099CF /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A437163521496411007099CF /* BridgeTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = BridgeTests.xctest; + remoteRef = A437163421496411007099CF /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12A121F61A0E00418AA4 /* Basic.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Basic.framework; + remoteRef = A4CB12A021F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12A321F61A0E00418AA4 /* CYaml.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = CYaml.framework; + remoteRef = A4CB12A221F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12A521F61A0E00418AA4 /* Clang_C.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Clang_C.framework; + remoteRef = A4CB12A421F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12A721F61A0E00418AA4 /* POSIX.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = POSIX.framework; + remoteRef = A4CB12A621F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12A921F61A0E00418AA4 /* PathKit.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = PathKit.framework; + remoteRef = A4CB12A821F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12AB21F61A0E00418AA4 /* SPMLibc.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SPMLibc.framework; + remoteRef = A4CB12AA21F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12AD21F61A0E00418AA4 /* SWXMLHash.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SWXMLHash.framework; + remoteRef = A4CB12AC21F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12AF21F61A0E00418AA4 /* SourceKit.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SourceKit.framework; + remoteRef = A4CB12AE21F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12B121F61A0E00418AA4 /* SourceKittenFramework.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = SourceKittenFramework.framework; + remoteRef = A4CB12B021F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12B321F61A0E00418AA4 /* Stencil.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Stencil.framework; + remoteRef = A4CB12B221F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12B521F61A0E00418AA4 /* StoryKitTool */ = { + isa = PBXReferenceProxy; + fileType = text; + path = StoryKitTool; + remoteRef = A4CB12B421F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12B721F61A0E00418AA4 /* StoryKitToolTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = file; + path = StoryKitToolTests.xctest; + remoteRef = A4CB12B621F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12B921F61A0E00418AA4 /* Utility.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Utility.framework; + remoteRef = A4CB12B821F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12BB21F61A0E00418AA4 /* Yams.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = Yams.framework; + remoteRef = A4CB12BA21F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + A4CB12BD21F61A0E00418AA4 /* clibc.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = clibc.framework; + remoteRef = A4CB12BC21F61A0E00418AA4 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + A43D613E21ECB9CB00993EC2 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A43D614F21ECB9CC00993EC2 /* LaunchScreen.storyboard in Resources */, + A43D614C21ECB9CC00993EC2 /* Assets.xcassets in Resources */, + A43D614A21ECB9CB00993EC2 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A4D2ABA6212321F400F2E110 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A4D2ABAF212321F400F2E110 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + A42954642135784500ECE976 /* Carthage copy frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/Carthage/Build/iOS/Bridge.framework", + ); + name = "Carthage copy frameworks"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#/usr/local/bin/carthage copy-frameworks\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + A43D613C21ECB9CB00993EC2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A43D614721ECB9CB00993EC2 /* SecondViewController.swift in Sources */, + A43D614321ECB9CB00993EC2 /* AppDelegate.swift in Sources */, + A43D614521ECB9CB00993EC2 /* FirstViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A4D2ABA3212321F400F2E110 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A434B855212DE9D10038783F /* Stage.swift in Sources */, + A43D49212131AFBB0050E617 /* Script.swift in Sources */, + A434B857212DE9E80038783F /* Narratable.swift in Sources */, + A4F0FEDF214845E1005C6481 /* Scriptable.swift in Sources */, + A4F1311321EBDD7400050802 /* Editor.swift in Sources */, + A4D5EC9021260DF700DC84E5 /* UIStoryboard+StoryKit.swift in Sources */, + A4C0999D212EF83000C3F9A7 /* Performer.swift in Sources */, + A434B85A212DEAF40038783F /* Scene.swift in Sources */, + A43D629E21ED1BE500993EC2 /* SceneDesignable.swift in Sources */, + A40748C021E5255700C79B34 /* ContainingController.swift in Sources */, + A4887DE1217A787F00E160D5 /* StaticallyIdentifiable.swift in Sources */, + A4A1C04721AF0B3300DBD0DD /* UIViewController+StoryKit.swift in Sources */, + A434B861212DED400038783F /* Transition.swift in Sources */, + A4D2ABC32123220B00F2E110 /* StoryKit.swift in Sources */, + A434B85E212DEB890038783F /* Storyboard.swift in Sources */, + A4A1C03721AC965E00DBD0DD /* SceneDescriptor.swift in Sources */, + A434B85C212DEB5D0038783F /* Story.swift in Sources */, + A40A348621528FDD005A720C /* SceneController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A4D2ABAD212321F400F2E110 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A43D613A21ECB96E00993EC2 /* Storyboards.swift in Sources */, + A4D2ABB7212321F400F2E110 /* StoryTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + A4080B79217A25BB00EB2419 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = Bridge; + targetProxy = A4080B78217A25BB00EB2419 /* PBXContainerItemProxy */; + }; + A43D615521ECBA5900993EC2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = A43D613F21ECB9CB00993EC2 /* StoryKitTestApp */; + targetProxy = A43D615421ECBA5900993EC2 /* PBXContainerItemProxy */; + }; + A4D2ABB4212321F400F2E110 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = A4D2ABA7212321F400F2E110 /* StoryKit */; + targetProxy = A4D2ABB3212321F400F2E110 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + A43D614821ECB9CB00993EC2 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A43D614921ECB9CB00993EC2 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + A43D614D21ECB9CC00993EC2 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + A43D614E21ECB9CC00993EC2 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + A43D615221ECB9CC00993EC2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + INFOPLIST_FILE = StoryKitTestApp/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.StoryKitTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A43D615321ECB9CC00993EC2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + INFOPLIST_FILE = StoryKitTestApp/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.StoryKitTestApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + A4D2ABBA212321F400F2E110 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + 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; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + A4D2ABBB212321F400F2E110 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + 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; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 4.2; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + A4D2ABBD212321F400F2E110 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = StoryKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.StoryKit; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + A4D2ABBE212321F400F2E110 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Automatic; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = StoryKit/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.StoryKit; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_VERSION = 4.2; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + A4D2ABC0212321F400F2E110 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + INFOPLIST_FILE = StoryKitTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.StoryKitTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StoryKitTestApp.app/StoryKitTestApp"; + }; + name = Debug; + }; + A4D2ABC1212321F400F2E110 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = ZXZ4CGK7P5; + INFOPLIST_FILE = StoryKitTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.impossibleflight.StoryKitTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/StoryKitTestApp.app/StoryKitTestApp"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + A43D615121ECB9CC00993EC2 /* Build configuration list for PBXNativeTarget "StoryKitTestApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A43D615221ECB9CC00993EC2 /* Debug */, + A43D615321ECB9CC00993EC2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A4D2ABA2212321F400F2E110 /* Build configuration list for PBXProject "StoryKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A4D2ABBA212321F400F2E110 /* Debug */, + A4D2ABBB212321F400F2E110 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A4D2ABBC212321F400F2E110 /* Build configuration list for PBXNativeTarget "StoryKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A4D2ABBD212321F400F2E110 /* Debug */, + A4D2ABBE212321F400F2E110 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A4D2ABBF212321F400F2E110 /* Build configuration list for PBXNativeTarget "StoryKitTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A4D2ABC0212321F400F2E110 /* Debug */, + A4D2ABC1212321F400F2E110 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = A4D2AB9F212321F400F2E110 /* Project object */; +} diff --git a/StoryKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/StoryKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..059da4c --- /dev/null +++ b/StoryKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/StoryKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/StoryKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/StoryKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/StoryKit.xcodeproj/xcshareddata/xcschemes/StoryKit.xcscheme b/StoryKit.xcodeproj/xcshareddata/xcschemes/StoryKit.xcscheme new file mode 100644 index 0000000..40af36f --- /dev/null +++ b/StoryKit.xcodeproj/xcshareddata/xcschemes/StoryKit.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/StoryKit.xcodeproj/xcshareddata/xcschemes/StoryKitTestApp.xcscheme b/StoryKit.xcodeproj/xcshareddata/xcschemes/StoryKitTestApp.xcscheme new file mode 100644 index 0000000..a007393 --- /dev/null +++ b/StoryKit.xcodeproj/xcshareddata/xcschemes/StoryKitTestApp.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/StoryKit/.DS_Store b/StoryKit/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Set { + return ["beginning"] + } + + private var stage: Stage +} + +class Edit: Operation, SceneActing { + private(set) var scene: AnyScene + private(set) var story: Story + + func sourceOverride() throws -> UIViewController? { + return try scene.sourceSceneController() + } + var dynamicSource: UIViewController? + var destination: UIViewController! + + var previousEdit: Edit? { + return self.dependencies.first as? Edit + } + + init(stage: Stage, scene: AnyScene, story: Story) { + self.stage = stage + self.scene = scene + self.story = story + super.init() + } + + override func main() { + if let previousEdit = previousEdit { + dynamicSource = previousEdit.destination + } + do { + destination = try scene.destinationSceneController() + var source = try sourceOverride() + if source == nil { + source = dynamicSource + } + scene.transition.worker(stage, self, source, destination, false, nil) + } + catch { + // We don't consider this to be fatal in release builds because the UI will still be left in some state that the user might potentially recover from. + assertionFailureOrPrint(String(describing: error)) + } + } + + private var stage: Stage +} + diff --git a/StoryKit/Info.plist b/StoryKit/Info.plist new file mode 100644 index 0000000..1007fd9 --- /dev/null +++ b/StoryKit/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/StoryKit/Narratable.swift b/StoryKit/Narratable.swift new file mode 100644 index 0000000..b07459b --- /dev/null +++ b/StoryKit/Narratable.swift @@ -0,0 +1,62 @@ +// +// Narratable.swift +// StoryKit +// +// Created by John Clayton on 8/22/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import UIKit + +public protocol Narratable { + // Appends scene to the current story (which is the receiver if the receiver is a story) and returns it + @discardableResult func segue(toScene scene: SceneDescriptor?, transition: TransitionProtocol, source: SceneDescriptor?, unlessConditionMet condition: Condition?) -> Self +} + +public extension Narratable { + @discardableResult func root(_ scene: SceneDescriptor?, unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: scene, transition: SystemTransition.root, source: nil, unlessConditionMet: condition) + } + + @discardableResult func select(_ scene: SceneDescriptor?, unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: scene, transition: SystemTransition.select, source: nil, unlessConditionMet: condition) + } + + @discardableResult func set(_ scene: SceneDescriptor?, unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: scene, transition: SystemTransition.set, source: nil, unlessConditionMet: condition) + } + + @discardableResult func embed(_ scene: SceneDescriptor?, in containing: SceneDescriptor, unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: scene, transition: SystemTransition.embed, source: containing, unlessConditionMet: condition) + } + + @discardableResult func push(_ scene: SceneDescriptor?, unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: scene, transition: SystemTransition.push, source: nil, unlessConditionMet: condition) + } + + @discardableResult func pop(unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: nil, transition: SystemTransition.pop, source: nil, unlessConditionMet: condition) + } + + @discardableResult func pop(_ scene: SceneDescriptor?, unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: scene, transition: SystemTransition.popTo, source: nil, unlessConditionMet: condition) + } + + @discardableResult func popToRoot(unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: nil, transition: SystemTransition.popToRoot, source: nil, unlessConditionMet: condition) + } + + @discardableResult func present(_ scene: SceneDescriptor?, from presenting: SceneDescriptor? = nil, unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: scene, transition: SystemTransition.present, source: presenting, unlessConditionMet: condition) + } + + @discardableResult func dismiss(_ scene: SceneDescriptor?, unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: scene, transition: SystemTransition.dismiss, source: nil, unlessConditionMet: condition) + } + + @discardableResult func unwind(_ scene: SceneDescriptor?, unlessConditionMet condition: Condition? = nil) -> Self { + return segue(toScene: scene, transition: SystemTransition.unwind, source: nil, unlessConditionMet: condition) + } +} + + diff --git a/StoryKit/Performer.swift b/StoryKit/Performer.swift new file mode 100644 index 0000000..3b2cd53 --- /dev/null +++ b/StoryKit/Performer.swift @@ -0,0 +1,313 @@ +// +// Actor.swift +// StoryKit +// +// Created by John Clayton on 8/23/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import UIKit + +extension Operation { + @discardableResult func passTo(_ operation: Operation, using block: @escaping ()->Void) -> BlockOperation { + let pipe = BlockOperation(block: block) + pipe.addDependency(self) + operation.addDependency(pipe) + return pipe + } +} + +class Performer: Operation { + enum State { + case waiting + case executing + case finished + } + + override var isAsynchronous: Bool { return true } + + fileprivate var state = State.waiting { + willSet { + willChangeValue(forKey: "state") + } + didSet { + didChangeValue(forKey: "state") + } + } + + var waiting: Bool { return state == .waiting } + + override var isExecuting: Bool { + let isExecuting = state == .executing + return isExecuting + } + + override var isFinished: Bool { + let isFinished = state == .finished + return isFinished + } + + override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set { + switch key { + case "isWaiting","isExecuting","isFinished": + return ["state"] + default: + return super.keyPathsForValuesAffectingValue(forKey: key) + } + } + + override func start() { + guard isCancelled == false else { return } + self.state = .executing + } +} + +class Director: Performer { + private(set) var animated: Bool + private(set) var ending: Story + + var beginning: Storyish? { + didSet { + actors = assembleCast() + } + } + + var onProgress: ((Storyish)->Void)? + + private(set) var story: Storyish? { + didSet(story) { + if let story = story { + onProgress?(story) + } + } + } + + private(set) var actors = [Operation]() + + + init(stage: Stage, story: Story, animated: Bool, completion: Ovation? = nil) { + self.stage = stage + ending = story + self.animated = animated + super.init() + if let block = completion { + self.completionBlock = { [weak self] in + DispatchQueue.main.async { + block((self?.actors.last as? Actor)?.destination) + } + } + } + } + + //MARK: Private + + private func assembleCast() -> [Operation] { + var actors = [Operation]() + + guard let beginning = beginning else { + return actors + } + + guard let plotToEnding = beginning.plotting(to: ending) else { + return actors + } + + let plotProgress = Story() + + + var previousActor: Actor? + for scene in plotToEnding.scenes { + let actor: Actor + if let condition = scene.condition { + actor = Spectactor(stage: stage, scene: scene, condition: condition, story: plotToEnding, animated: animated) + } else { + actor = Actor(stage: stage, scene: scene, story: plotToEnding, animated: animated) + } + + if let previousActor = previousActor { + let handoff = previousActor.passTo(actor) { + actor.dynamicSource = previousActor.destination + } + actors.append(handoff) + } else { + do { + if let source = try beginning.scenes.last?.destinationSceneController() { + actor.dynamicSource = source + } + } catch { + // If the first actor needed a source and didn't get one it will explode later. But, we still want to know that there was an error getting the source for the first scene even if the actor is fine without it. + assertionFailureOrPrint(String(describing: error)) + } + } + + actor.completionBlock = { + plotProgress.append(scene) + let currentDraft = plotProgress.relative(to: beginning) + self.story = currentDraft + } + + actors.append(actor) + previousActor = actor + } + + if let previousActor = previousActor { + self.addDependency(previousActor) + } + + return actors + } + + private var stage: Stage +} + +//MARK: Director: Operation + +extension Director { + class func keyPathsForValuesAffectingValueForReady() -> Set { return ["actors"] } + + override var isReady: Bool { + return super.isReady && beginning != nil + } + + override func start() { + guard isCancelled == false else { return } + self.state = .finished + } + + override func cancel() { + super.cancel() + self.actors.forEach { $0.cancel() } + } +} + +public protocol SceneActing: class { + var destination: UIViewController! { get set } +} + +class Actor: Performer, SceneActing { + fileprivate var stage: Stage + private(set) var scene: AnyScene + private(set) var story: Story + private(set) var animated: Bool + + func sourceOverride() throws -> UIViewController? { + return try scene.sourceSceneController() + } + var dynamicSource: UIViewController? + var destination: UIViewController! + + var completedTransition: Bool = false + + init(stage: Stage, scene: AnyScene, story: Story, animated: Bool) { + self.stage = stage + self.scene = scene + self.story = story + self.animated = animated + super.init() + } + + override func start() { + guard isCancelled == false else { return } + + super.start() + + do { + destination = try scene.destinationSceneController() + var source = try sourceOverride() + if source == nil { + source = dynamicSource + } + scene.transition.worker(stage, self, source, destination, animated, { complete in + self.finishTransition(completed: complete) + }) + } + catch { + // We don't consider this to be fatal in release builds because the UI will still be left in some state that the user might potentially recover from. + assertionFailureOrPrint(String(describing: error)) + state = .finished + } + } + + func finishTransition(completed: Bool) { + completedTransition = completed + self.state = .finished + } +} + +class Spectactor: Actor { + init(stage: Stage, scene: AnyScene, condition: Condition, story: Story, animated: Bool) { + super.init(stage: stage, scene: scene, story: story, animated: animated) + condition.observe { [weak self] event in + guard let self = self else { return } + switch event { + case .next(let flag): + self.conditionValue = flag + case .error(let error): + assertionFailureOrPrint("Got error while waiting on condition. \(scene) (\(error))") + self.state = .finished + case .completed: + self.state = .finished + } + } + } + + override func start() { + guard isCancelled == false else { return } + guard conditionValue == false else { + state = .finished + return + } + super.start() + } + + override func finishTransition(completed: Bool) { + finishIfConditionSatisfied() + } + + func finishIfConditionSatisfied() { + if isExecuting && conditionValue { + let inverse = scene.transition.inverse + inverse.worker(stage, self, dynamicSource, destination, animated) { complete in + self.state = .finished + } + } + } + + private var haveInitialConditionValue: Bool = false + private var conditionValue = false { + didSet { + haveInitialConditionValue = true + finishIfConditionSatisfied() + } + } + + + //MARK: Operation + + class func keyPathsForValuesAffectingValueForReady() -> Set { return ["haveInitialConditionValue"] } + + override var isReady: Bool { + let superIsReady = super.isReady + return superIsReady && haveInitialConditionValue + } + +} + + + + + + + + + + + + + + + + + + + diff --git a/StoryKit/Scene.swift b/StoryKit/Scene.swift new file mode 100644 index 0000000..eed3345 --- /dev/null +++ b/StoryKit/Scene.swift @@ -0,0 +1,257 @@ +// +// Scene.swift +// StoryKit +// +// Created by John Clayton on 8/22/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import UIKit + +protocol PathRepresentable { + var segmentRepresentation: String { get } +} + +protocol SceneProtocol: class, Scriptable, PathRepresentable, CustomStringConvertible { + var source: SceneDescriptor? { get } + var destination: SceneDescriptor? { get } + var transition: TransitionProtocol { get } + var condition: Condition? { get } + var junctionWith: SceneProtocol? { get set } + var isJunction: Bool { get } + var isRoot: Bool { get } + var name: String { get } + func sourceSceneController() throws -> UIViewController? + func destinationSceneController() throws -> UIViewController? + func inverse() throws -> SceneProtocol +} + +//MARK: Scriptable + +extension SceneProtocol { + func matches(string: String) -> Bool { + return segmentRepresentation.caseInsensitiveCompare(string) == .orderedSame + } +} + +//MARK: PathRepresentable + +extension SceneProtocol { + var segmentRepresentation: String { + return isRoot ? "/" : name + } +} + +extension SceneProtocol { + var isJunction: Bool { + return junctionWith != nil + } + + var isRoot: Bool { + return transition.isRoot + } + + var name: String { + return destination?.name ?? "???" + } + + func sourceSceneController() throws -> UIViewController? { + return try source?.sceneController() + } + + func inverse() throws -> SceneProtocol { + var descriptor: SceneDescriptor? + if let destination = destination { + let factory = { + return try destination.sceneController() + } + descriptor = InverseDescriptor(factory: factory) + } + return Scene(descriptor: descriptor, transition: transition.inverse) + } +} + +extension SceneProtocol { + /// Equality for scenes really is universal across all implmentations: as far as the stage is concerned we have the same scene if it has the same descriptor (type and identifier) and transition (conversely, it is an error to represent different scenes with the same scene descriptor). + func isEqual(_ other: SceneProtocol) -> Bool { + var destinationsEqual = false + switch (self.destination, other.destination) { + case let (.some(left), .some(right)): + destinationsEqual = left == right + case (.none, .none): + destinationsEqual = true + case (.some(_), .none), (.none, .some(_)): + destinationsEqual = false + } + return destinationsEqual && self.transition == other.transition + } +} + +extension SceneProtocol { + var description: String { + let address = Int(bitPattern: ObjectIdentifier(self)) + return String(format: "<%@ %0llx> name = %@, transition = %@", String(describing: Self.self), address, name, String(describing: transition)) + } + var shorthand: String { + return "\(transition.operator)(\(name))" + } +} + +class Scene: SceneProtocol { + private(set) var source: SceneDescriptor? + private(set) var destination: SceneDescriptor? + private(set) var transition: TransitionProtocol + private(set) var condition: Condition? + var junctionWith: SceneProtocol? + + init(descriptor: SceneDescriptor?, transition: TransitionProtocol, source: SceneDescriptor? = nil, condition: Condition? = nil) { + self.source = source + self.destination = descriptor + self.transition = transition + self.condition = condition + } + + func destinationSceneController() throws -> UIViewController? { + if let viewController = _viewController { + return viewController + } + let controller = try destination?.sceneController() + _viewController = controller + return controller + } + + private var _viewController: UIViewController? +} + +class InputScene : SceneProtocol { + private(set) var source: SceneDescriptor? + private(set) var destination: SceneDescriptor? + private(set) var transition: TransitionProtocol + private(set) var condition: Condition? + var junctionWith: SceneProtocol? + var name: String { + return String(describing: input) + } + + private(set) var input: Input + + init(descriptor: SceneDescriptor, factory: @escaping (Input) -> SceneDescriptor, input: Input, transition: TransitionProtocol, source: SceneDescriptor? = nil, condition: Condition? = nil) { + self.source = source + self.destination = descriptor + self.factory = factory + self.input = input + self.transition = transition + self.condition = condition + } + + func destinationSceneController() throws -> UIViewController? { + if let viewController = _viewController { + return viewController + } + let descriptor: SceneDescriptor = factory(input) + let controller = try descriptor.sceneController() + _viewController = controller + return controller + } + + private var factory: (Input) -> SceneDescriptor + private var _viewController: UIViewController? +} + +class StaticScene: SceneProtocol { + let source: SceneDescriptor? = nil + private(set) var destination: SceneDescriptor? + private(set) var transition: TransitionProtocol + let condition: Condition? = nil + var junctionWith: SceneProtocol? + + init(descriptor: SceneDescriptor, viewController: UIViewController, transition: TransitionProtocol) { + self.destination = descriptor + _viewController = viewController + self.transition = transition + } + + func destinationSceneController() throws -> UIViewController? { + return _viewController + } + + private var _viewController: UIViewController +} + +//MARK: A concrete type erased box so we can get Equatable behavior for all SceneTypes + +extension SceneProtocol { + func asAnyScene() -> AnyScene { + return AnyScene(self) + } +} + +public class AnyScene: SceneProtocol { + private(set) var value: SceneProtocol + + init(_ value: TransitionType) { + self.value = value + } + + var source: SceneDescriptor? { + return value.source + } + + var destination: SceneDescriptor? { + return value.destination + } + var transition: TransitionProtocol { + return value.transition + } + + var condition: Condition? { + return value.condition + } + + var junctionWith: SceneProtocol? { + get { + return value.junctionWith + } + set { + value.junctionWith = newValue + } + } + + var name: String { + return value.name + } + + func sourceSceneController() throws -> UIViewController? { + return try value.sourceSceneController() + } + + func destinationSceneController() throws -> UIViewController? { + return try value.destinationSceneController() + } +} + +extension AnyScene: Equatable { + // Uses the protocol's definition of equality + public static func==(lhs: AnyScene, rhs: AnyScene) -> Bool { + return lhs.isEqual(rhs) + } +} + +extension AnyScene: CustomStringConvertible { + public var description: String { + let address = Int(bitPattern: ObjectIdentifier(self)) + return String(format: "<%@ %0llx> value = %@,", String(describing: AnyScene.self), address, String(describing: value)) + } +} + +extension AnyScene: PathRepresentable { + var segmentRepresentation: String { + return value.segmentRepresentation + } +} + +extension AnyScene: Scriptable { + func matches(string: String) -> Bool { + return value.matches(string: string) + } +} diff --git a/StoryKit/SceneController.swift b/StoryKit/SceneController.swift new file mode 100644 index 0000000..929610d --- /dev/null +++ b/StoryKit/SceneController.swift @@ -0,0 +1,138 @@ +// +// UIViewController+StoryKit.swift +// StoryKit +// +// Created by John Clayton on 9/19/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import UIKit +import Bridge + +fileprivate extension NSObjectProtocol { + var moduleName: String? { + let nameComponents = NSStringFromClass(type(of: self)).split(separator: ".") + guard nameComponents.count > 1 else { + return nil + } + return String(nameComponents.first!) + } +} + +public protocol SceneController { + var sceneDescriptor: SceneDescriptor { get } +// func getSceneDescriptor() -> S +// func setSceneDescriptor(_ descriptor: S) +} + +extension UIViewController: SceneController { + + fileprivate struct AssociationKeys { + static var frozenDescriptor = "frozenDescriptor" + } + + /// A descriptor that is frozen in time to return only the receiver as the view controller +// private var frozenDescriptor: SceneDescriptor? { +// get { +// if let frozenDescriptor: FrozenDescriptor = get(associatedObjectForKey: &AssociationKeys.frozenDescriptor) { +// return frozenDescriptor +// } +// return nil +// } +// set { +// var frozenDescriptor: FrozenDescriptor? = nil +// if let descriptor = newValue { +// frozenDescriptor = FrozenDescriptor(descriptor, sceneController: self) +// } +// set(associatedObject: frozenDescriptor, forKey: &AssociationKeys.frozenDescriptor) +// } +// } + + func freeze(descriptor: S) { + let frozenDescriptor = FrozenDescriptor(descriptor, sceneController: self) + objc_setAssociatedObject(self as Any, &AssociationKeys.frozenDescriptor, (frozenDescriptor as SceneDescriptor), .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + + func getFrozenDescriptor() -> SceneDescriptor? { + if let frozenDescriptor = objc_getAssociatedObject(self, &AssociationKeys.frozenDescriptor) { + // There is a bug in swift that won't allow casting from Any to a protocol directly if the underlying type is a struct. + // Cast to AnyObject first to work around this + // https://bugs.swift.org/browse/SR-3871 + let asObject = frozenDescriptor as AnyObject + let descriptor = asObject as? SceneDescriptor + return descriptor + } + return nil + } + + private var inferredSceneDescriptor: SceneDescriptor? { + guard let storyboardName = self.storyboardName, let restorationIdentifier = self.restorationIdentifier else { + return nil + } + guard let descriptor = StoryKit.descriptor(forName: storyboardName, identifier: restorationIdentifier) else { + return nil + } +// // Once we have inferred a descriptor we need to freeze it so it returns us as the view controller +// frozenDescriptor = descriptor +// return frozenDescriptor + return descriptor + } + +// private func inferDescriptor() -> S? { +// guard let storyboardName = self.storyboardName, let restorationIdentifier = self.restorationIdentifier else { +// return nil +// } +// if let inferredDescriptor: S = StoryKit.descriptor(forName: storyboardName, identifier: restorationIdentifier) { +// // Once we have inferred a descriptor we need to freeze it so it returns us as the view controller +// freeze(descriptor: inferredDescriptor) +// if let frozenDescriptor = getFrozenDescriptor() { +// return frozenDescriptor as? S +// } +// } +// return nil +// } + + public var sceneDescriptor: SceneDescriptor { + get { + if let descriptor = getFrozenDescriptor() { + return descriptor + } + if let descriptor: SceneDescriptor = inferredSceneDescriptor { + return descriptor + } + if assertViewControllerNotSceneController { + let currentModule = UIApplication.shared.delegate?.moduleName + if moduleName == currentModule { + assertionFailure("Application module view controller \(self) did not have a scene descriptor!") + } + } + return staticDescriptor + } + } + +// public func getSceneDescriptor() -> S { +// if let descriptor = getFrozenDescriptor() as? S { +// return descriptor +// } +// if let descriptor: S = inferDescriptor() { +// return descriptor +// } +// if assertViewControllerNotSceneController { +// let currentModule = UIApplication.shared.delegate?.moduleName +// if moduleName == currentModule { +// assertionFailure("Application module view controller \(self) did not have a scene descriptor!") +// } +// } +// return staticDescriptor as! S +// } +// +// public func setSceneDescriptor(_ descriptor: S) { +// freeze(descriptor: descriptor) +// } + + + var staticDescriptor: StaticDescriptor { + return StaticDescriptor(sceneController: self) + } +} + diff --git a/StoryKit/SceneDescriptor.swift b/StoryKit/SceneDescriptor.swift new file mode 100644 index 0000000..6d6deea --- /dev/null +++ b/StoryKit/SceneDescriptor.swift @@ -0,0 +1,147 @@ +// +// SceneDescriptor.swift +// StoryKit +// +// Created by John Clayton on 11/26/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import UIKit + +public typealias TypeIdentifier = String +public typealias SceneIdentifier = String + +public protocol _SceneDescriptor { + var typeIdentifier: TypeIdentifier { get } + var name: String { get } + var identifier: SceneIdentifier { get } + func isEqual(to: _SceneDescriptor) -> Bool +} + +public protocol SceneDescriptor: _SceneDescriptor { + func sceneController() throws -> UIViewController +} + +public protocol SceneDescriptorConstructing { + static func by(restorationIdentifier: String) -> SceneDescriptor? +} + +public protocol StoryboardSceneDescriptor: SceneDescriptor, SceneDescriptorConstructing { + static var restorationIdentifiers: [Self] { get } +} + +public protocol SceneControllerInitializing { + func didLoad(sceneController: V) +} + +public extension _SceneDescriptor { + var typeIdentifier: TypeIdentifier { + return "\(String(describing: Self.self))" + } + var name: String { + let mirror = Mirror(reflecting: self) + if let label = mirror.children.first?.label { + return label + } else { + return String(describing:self) + } + } + var identifier: SceneIdentifier { + return "\(Self.self).\(String(describing: self))" + } + func isEqual(to other: _SceneDescriptor) -> Bool { + return self.identifier == other.identifier + } +} + +func ==(lhs: _SceneDescriptor, rhs: _SceneDescriptor) -> Bool { + return lhs.isEqual(to: rhs) +} + +public extension SceneDescriptor { + /// Provides a default method for loading a view controller for the receiver from a storyboard matching the receiver's type. If the scope is `.container` then the returned view controller may have been cached after being initialized by the storyboard. + /// + /// - Parameters: + /// - scope: <#scope description#> + /// - initializer: <#initializer description#> + /// - Throws: <#throws value description#> + func sceneControllerFromStoryboard(inScope scope: Scope = .transient, initializer: ((V) -> Void)? = nil) throws -> V { + let board = try Storyboard.described(by: self) + let controller: V = try board.viewController(forScene: self, scope: scope, initializer: initializer) + return controller + } + + /// Calls `viewController()` and returns nil if that function throws an exception. Fires an assertion in -Onone builds if an exception is trapped. + var sceneController: UIViewController? { + do { + return try sceneController() + } catch { + assertionFailure("Failed to load view controller for descriptor \(self)") + return nil + } + } +} + +public extension StoryboardSceneDescriptor { + static func by(restorationIdentifier: String) -> SceneDescriptor? { + for r in Self.restorationIdentifiers { + if "\(r.name)" == restorationIdentifier { + return r + } + } + return nil + } +} + +protocol _InternalDescriptor {} + +struct FrozenDescriptor : SceneDescriptor, _InternalDescriptor { + public init(_ descriptor: DescriptorType, sceneController: UIViewController) { + self.descriptor = descriptor + _sceneController = sceneController + } + + public func describedType() -> T.Type { + return DescriptorType.self as! T.Type + } + public var typeIdentifier: String { return descriptor.typeIdentifier } + + public var name: String { return descriptor.name } + public var identifier: SceneIdentifier { return descriptor.identifier } + public func sceneController() throws -> UIViewController { return _sceneController } + public func isEqual(to other: SceneDescriptor) -> Bool { return descriptor.isEqual(to: other) } + + private(set) public var descriptor: DescriptorType + private weak var _sceneController: UIViewController! +} + +struct InverseDescriptor: SceneDescriptor { + init(factory: @escaping () throws -> UIViewController) { + self.factory = factory + } + + var identifier: String { + return "../" + } + + private var factory: () throws -> UIViewController + func sceneController() throws -> UIViewController { + return try factory() + } +} + +/// A descriptor that can be built as a last resort from a scene controller that does not provide a descriptor using an identifier that represents that instance of the scene controller +struct StaticDescriptor: SceneDescriptor, _InternalDescriptor { + init(sceneController: UIViewController) { + self._sceneController = sceneController + } + + public var identifier: String { + return _sceneController.staticIdentifier + } + + private var _sceneController: UIViewController + public func sceneController() throws -> UIViewController { + return _sceneController + } +} diff --git a/StoryKit/SceneDesignable.swift b/StoryKit/SceneDesignable.swift new file mode 100644 index 0000000..4fbcdda --- /dev/null +++ b/StoryKit/SceneDesignable.swift @@ -0,0 +1,25 @@ +// +// SceneDesignable.swift +// StoryKit +// +// Created by John Clayton on 10/19/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import UIKit + +/// An internal protocol that allows an input signature, e.g. "(String)", to be set in IB which the generator will use to generate the scene descriptor case for the receiver, e.g. -> "photos(String)" +protocol SceneDesignable { + var inputSignature: String? { get } +} + +extension UIViewController: SceneDesignable { + // This is just a stub to let IB generate the value in the storyboard for generator to consume. We don't actually care about the value at runtime. + @IBInspectable public var inputSignature: String? { + get { return nil } + set { } + } +} + + + diff --git a/StoryKit/Script.swift b/StoryKit/Script.swift new file mode 100644 index 0000000..8cbc341 --- /dev/null +++ b/StoryKit/Script.swift @@ -0,0 +1,421 @@ +// +// Script.swift +// StoryKit +// +// Created by John Clayton on 8/25/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import UIKit + +protocol Scriptable { + func matches(string: String) -> Bool +} + +struct InputMatcher { + enum Error: Swift.Error { + case couldNotTransformValueToType(value: Any, type: Any.Type) + } + + typealias Transformer = (String) -> Input + + let pattern: String + let regularExpression: NSRegularExpression + + init!(pattern: String, options: NSRegularExpression.Options = [], transform: @escaping Transformer) { + self.pattern = pattern + self.regularExpression = try! NSRegularExpression(pattern: pattern, options: options) + self.transform = transform + } + + func matches(string: String) -> Bool { + return regularExpression.rangeOfFirstMatch(in: string, options: [.anchored], range: NSMakeRange(0, (string as NSString).length)).location != NSNotFound + } + + func value(from: String) throws -> Input { + let range = from.startIndex.. Any + var label: String { get } + var pattern: String { get } + var transform: AnyTransform { get } + var inputString: String! { get } +} + +protocol MutableInputCapturing: InputCapturing { + var inputString: String! { get set } +} + +class InputCaptureScene : SceneProtocol { + enum Error: Swift.Error, CustomStringConvertible { + case missingInput + var description: String { + switch self { + case .missingInput: + return "Tried building a scene with missing input \(String(describing: Input.self))" + } + } + } + + let source: SceneDescriptor? = nil + private(set) var destination: SceneDescriptor? + private(set) var transition: TransitionProtocol + let condition: Condition? = nil + var junctionWith: SceneProtocol? + var name: String { + return "\(matcher.pattern)" + } + + private(set) var matcher: InputMatcher + var inputString: String! + + init(factory: @escaping (Input) -> SceneDescriptor, capture: String, label: String? = nil, transform: @escaping (String) -> Input, transition: TransitionProtocol) { + self.factory = factory + self.matcher = InputMatcher(pattern: capture, transform: transform) + _label = label + self.transition = transition + } + + func destinationSceneController() throws -> UIViewController? { + guard let inputString = inputString else { + throw Error.missingInput + } + let input = try matcher.value(from: inputString) + if let viewController = _viewController { + return viewController + } + let descriptor: SceneDescriptor = factory(input) + let controller = try descriptor.sceneController() + _viewController = controller + destination = descriptor + return controller + } + + private var factory: (Input) -> SceneDescriptor + private var _label: String? + private var _viewController: UIViewController? +} + +extension InputCaptureScene: Scriptable { + func matches(string: String) -> Bool { + return matcher.matches(string: string) + } +} + +extension InputCaptureScene: PathRepresentable { + var segmentRepresentation: String { + if let _ = inputString { + return inputString + } + return "\(label)=(\(pattern))" + } +} + +extension InputCaptureScene: InputCapturing { + var label: String { + return _label ?? destination?.name ?? "???" + } + var pattern: String { + return matcher.pattern + } + var transform: (String) -> Any { + return matcher.transform as (String) -> Any + } +} +extension InputCaptureScene: MutableInputCapturing {} + +extension InputCaptureScene: CustomStringConvertible { + var description: String { + let address = Int(bitPattern: ObjectIdentifier(self)) + return String(format: "<%@ %0llx> name = %@, transition = %@, label = %@", String(describing: InputCaptureScene.self), address, name, String(describing: transition), label) + } + var shorthand: String { + return "\(transition.operator)(\(label)=\(pattern))" + } +} + +class Prop: SceneProtocol { + let source: SceneDescriptor? = nil + let destination: SceneDescriptor? = nil + let transition: TransitionProtocol = SystemTransition.none + let condition: Condition? = nil + var junctionWith: SceneProtocol? { + get { return nil } + set {} + } + + var name: String + init(name: String) { + self.name = name + } + + func destinationSceneController() throws -> UIViewController? { return nil } +} + +public final class Script: Storyish { + public var name: String? + private(set) public var scenes: [AnyScene] + private(set) public var base: Storyish? = nil + private(set) public var stage: Stage? = nil + private(set) public var identifier: UUID = UUID() + + init(scenes: [AnyScene] = [], stage: Stage? = nil) { + self.scenes = scenes + self.stage = stage + } + + func asStory() -> Story { + //???: Does it make sense to validate the scenes have the requisite input here? + return Story(scenes, stage: stage) + } +} + +extension Script: CustomStringConvertible { + public var description: String { + let address = Int(bitPattern: ObjectIdentifier(self)) + return String(format: "<%@ %0llx> name = %@, scenes = %@", String(describing: Script.self), address, String(describing: name), proofedScenes()) + } +} + +extension Script: Composable { + @discardableResult public func append(_ scene: AnyScene) -> Script { + let previousScene = scenes.last + scenes.append(scene) + if previousScene != nil && previousScene!.transition.isJunction { + previousScene!.junctionWith = scene + } + return self + } +} + +extension Script: Narratable { + public func segue(toScene scene: SceneDescriptor?, transition: TransitionProtocol, source: SceneDescriptor? = nil, unlessConditionMet condition: Condition? = nil) -> Script { + return self.append(Scene(descriptor: scene, transition: transition, source: source, condition: condition)) + } +} + +public extension Narratable where Self == Script { + @discardableResult func plot(futureScene scene: @escaping (String) -> S, capture pattern: String, label: String? = nil, transition: T, unlessConditionMet condition: Condition? = nil) -> Script { + return self.plot(futureScene: scene, capture: pattern, label: label, transform: {$0}, transition: transition) + } + + @discardableResult func plot(futureScene scene: @escaping (Input) -> S, capture pattern: String, label: String? = nil, transform: @escaping (String) -> Input, transition: T, unlessConditionMet condition: Condition? = nil) -> Script { + let scene = InputCaptureScene(factory: scene, capture: pattern, label: label, transform: transform, transition: transition) + return self.append(scene) + } +} + +public extension Narratable where Self == Script { + @discardableResult func root(_ scene: @escaping (String) -> S, capture pattern: String, label: String? = nil, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transition: SystemTransition.root) + } + + @discardableResult func root(_ scene: @escaping (Input) -> S, capture pattern: String, label: String? = nil, transform: @escaping (String) -> Input, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transform: transform, transition: SystemTransition.root) + } + + @discardableResult func select(_ scene: @escaping (String) -> S, capture pattern: String, label: String? = nil, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transition: SystemTransition.select) + } + + @discardableResult func select(_ scene: @escaping (Input) -> S, capture pattern: String, label: String? = nil, transform: @escaping (String) -> Input, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transform: transform, transition: SystemTransition.select) + } + + @discardableResult func set(_ scene: @escaping (String) -> S, capture pattern: String, label: String? = nil, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transition: SystemTransition.set) + } + + @discardableResult func set(_ scene: @escaping (Input) -> S, capture pattern: String, label: String? = nil, transform: @escaping (String) -> Input, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transform: transform, transition: SystemTransition.set) + } + + @discardableResult func push(_ scene: @escaping (String) -> S, capture pattern: String, label: String? = nil, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transition: SystemTransition.push) + } + + @discardableResult func push(_ scene: @escaping (Input) -> S, capture pattern: String, label: String? = nil, transform: @escaping (String) -> Input, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transform: transform, transition: SystemTransition.push) + } + + @discardableResult func pop(_ scene: @escaping (String) -> S, capture pattern: String, label: String? = nil, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transition: SystemTransition.pop) + } + + @discardableResult func pop(_ scene: @escaping (Input) -> S, capture pattern: String, label: String? = nil, transform: @escaping (String) -> Input, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transform: transform, transition: SystemTransition.pop) + } + + @discardableResult func present(_ scene: @escaping (String) -> S, capture pattern: String, label: String? = nil, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transition: SystemTransition.present) + } + + @discardableResult func present(_ scene: @escaping (Input) -> S, capture pattern: String, label: String? = nil, transform: @escaping (String) -> Input, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transform: transform, transition: SystemTransition.present) + } + + @discardableResult func dismiss(_ scene: @escaping (String) -> S, capture pattern: String, label: String? = nil, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transition: SystemTransition.dismiss) + } + + @discardableResult func dismiss(_ scene: @escaping (Input) -> S, capture pattern: String, label: String? = nil, transform: @escaping (String) -> Input, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transform: transform, transition: SystemTransition.dismiss) + } + + @discardableResult func unwind(_ scene: @escaping (String) -> S, capture pattern: String, label: String? = nil, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transition: SystemTransition.unwind) + } + + @discardableResult func unwind(_ scene: @escaping (Input) -> S, capture pattern: String, label: String? = nil, transform: @escaping (String) -> Input, unlessConditionMet condition: Condition? = nil) -> Self { + return plot(futureScene: scene, capture: pattern, label: label, transform: transform, transition: SystemTransition.unwind) + } + + @discardableResult func prop(_ name: String) -> Self { + return self.append(Prop(name: name)) + } +} + +extension Script: Performable { + public func insert() { + self.asStory().insert() + } + public func perform(animated: Bool = true, completion: Ovation? = nil ) { + self.asStory().perform(animated: animated, completion: completion) + } +} + + +//MARK: Value binding & URL convertibility + + + // We need a composit of input capturing and scene to handle capture scenes while enforcing the mutability rules of input capturing +protocol InputCapturingScene: InputCapturing, SceneProtocol { + func mutableCopy() -> MutableInputCapturingScene +} +protocol MutableInputCapturingScene: MutableInputCapturing, SceneProtocol {} + +extension InputCaptureScene: InputCapturingScene { + func mutableCopy() -> MutableInputCapturingScene { + return InputCaptureScene(factory: factory, capture: matcher.pattern, transform: matcher.transform, transition: transition) + } +} +extension InputCaptureScene: MutableInputCapturingScene {} + +public protocol URLConvertibility { + var pathRepresentation: String { get } + var captureSegments: [(label: String, pattern: String)] { get } + func bind(inputs: [String]) throws -> Script + func bind(pathSegments: [String]) throws -> Script +} + +extension Script: URLConvertibility { + enum Error: Swift.Error { + case inputCaptureCountMismatch(expected: Int, got: Int) + case inputCaptureIndexOverflow(got: Int, count: Int) + case inputScenePatternMismatch(segment: String, pattern: String) + case segmentSceneCountMismatch(expected: Int, got: Int) + case segmentIndexOverflow(got: Int, count: Int) + case segmentSceneMissingInput(scene: SceneProtocol) + case segmentScenePatternMismatch(segment: String, pattern: String) + } + + var pathScenes: [AnyScene] { + var pathScenes = [AnyScene]() + for scene in scenes { + guard !scene.isJunction else { continue } + pathScenes.append(scene) + } + return pathScenes + } + + public var pathRepresentation: String { + var pathComponents = [String]() + for scene in pathScenes { + if scene.isRoot { + pathComponents.append("") + } else { + pathComponents.append(scene.segmentRepresentation) + } + } + return pathComponents.joined(separator: "/") + } + + private var captureScenes: [InputCapturingScene] { + return pathScenes.compactMap { $0.value as? InputCapturingScene } + } + + public var captureSegments: [(label: String, pattern: String)] { + return captureScenes.map { ($0.label, $0.pattern) } + } + + public func bind(inputs: [String]) throws -> Script { + let captureScenes = self.captureScenes + guard inputs.count == captureScenes.count else { + throw Error.inputCaptureCountMismatch(expected: captureScenes.count, got: inputs.count) + } + let script = Script(stage: stage) + var captureIndex = 0 + for scene in scenes { + if let captureScene = scene.value as? InputCapturingScene { + guard captureIndex < captureScenes.count else { + throw Error.inputCaptureIndexOverflow(got: captureIndex, count: captureScenes.count) + } + let input = inputs[captureIndex] + captureIndex += 1 + guard captureScene.matches(string: input) else { + throw Error.inputScenePatternMismatch(segment: input, pattern: captureScene.pattern) + } + var mutableScene = captureScene.mutableCopy() + mutableScene.inputString = input + script.append(mutableScene) + } else { + script.append(scene) + } + } + return script + } + + public func bind(pathSegments: [String]) throws -> Script { + let pathScenes = self.pathScenes + guard pathSegments.count == pathScenes.count else { + throw Error.inputCaptureCountMismatch(expected: pathScenes.count, got: pathSegments.count) + } + let script = Script(stage: stage) + var segmentIndex = 0 + for scene in scenes { + var segment: String? = nil + if pathScenes.contains(scene) { + guard segmentIndex < pathScenes.count else { + throw Error.segmentIndexOverflow(got: segmentIndex, count: pathScenes.count) + } + segment = pathSegments[segmentIndex] + segmentIndex += 1 + } + + if let captureScene = scene.value as? InputCapturingScene { + guard let segment = segment else { + throw Error.segmentSceneMissingInput(scene: captureScene) + } + guard captureScene.matches(string: segment) else { + throw Error.segmentScenePatternMismatch(segment: segment, pattern: captureScene.pattern) + } + var mutableScene = captureScene.mutableCopy() + mutableScene.inputString = segment + script.append(mutableScene) + } else { + script.append(scene) + } + } + return script + } +} + diff --git a/StoryKit/Scriptable.swift b/StoryKit/Scriptable.swift new file mode 100644 index 0000000..38693be --- /dev/null +++ b/StoryKit/Scriptable.swift @@ -0,0 +1,10 @@ +// +// Scriptable.swift +// StoryKit +// +// Created by John Clayton on 9/11/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import UIKit + diff --git a/StoryKit/Stage.swift b/StoryKit/Stage.swift new file mode 100644 index 0000000..244c81c --- /dev/null +++ b/StoryKit/Stage.swift @@ -0,0 +1,241 @@ +// +// Stage.swift +// StoryKit +// +// Created by John Clayton on 8/22/18. +// Copyright © 2018 Impossible Flight, LLC. All rights reserved. +// + +import UIKit + +public typealias Ovation = (UIViewController?)->Void + +public enum Event { + case next(Bool) + case error(Error) + case completed +} + +public protocol Condition { + func observe(eventBlock: @escaping (Event)->Void) +} + +public class Stage { + public let window: UIWindow + public var registeredScripts: [Script] { + let registeredScripts = scripts + return registeredScripts + } + + public init(window: UIWindow) throws { + self.window = window + if let rootViewController = window.rootViewController { + try rootViewController.sceneDescriptor.registerInBoard(viewController: rootViewController) + } + } + + @discardableResult public func register(scriptAndInitialize initializer: (Script) -> Void) -> Script { + let script = Script(stage: self) + register(script: script) + initializer(script) + return script + } + + public func register(script: Script) { + scripts.append(script) + } + + public func perform(_ story: Story, animated: Bool = true, completion: Ovation? = nil ) { + let director = Director(stage: self, story: story, animated: animated, completion: completion) + let directors = performanceQueue.operations.filter { $0 is Director } + if let previousDirector = directors.last { + let pipe = previousDirector.passTo(director) { + director.beginning = self.story + self.performanceQueue.addOperations(director.actors, waitUntilFinished: false) + } + performanceQueue.addOperation(pipe) + } else { + director.beginning = self.story + performanceQueue.addOperations(director.actors, waitUntilFinished: false) + } + + director.onProgress = { story in + self.currentPerformance = story + } + + performanceQueue.addOperation(director) + } + + public func insert(_ story: Story) { + performanceQueue.isSuspended = true + defer { + performanceQueue.isSuspended = false + } + let editor = Editor(stage: self, beginning: self.story, ending: story) + + var operations = editor.dependencies + operations.append(editor) + + for operation in operations { + operation.start() + } + } + + public var story: Storyish { + do { + return try staticStory(fromNode: window.rootViewController, transition: SystemTransition.root) + } catch { + assertionFailureOrPrint("Could not derive current story from UI state \(error)") + return StaticStory() + } + } + + private func staticStory(fromNode node: UIViewController?, transition: T) throws -> StaticStory { + let scenes: [SceneProtocol] = try staticScenes(fromNode: node, transition: transition) + return StaticStory(scenes) + } + + private func staticScenes(fromNode node: UIViewController?, transition: T) throws -> [StaticScene] { + var scenes = [StaticScene]() + + guard let node = node else { return scenes } + + let descriptor = node.sceneDescriptor + + let scene = StaticScene(descriptor: descriptor, viewController: node, transition: transition) + scenes.append(scene) + + switch node { + case let tabs as UITabBarController: + scenes += try staticScenes(fromNode: tabs.selectedViewController, transition: SystemTransition.select) + case let nav as UINavigationController: + let stack = nav.viewControllers + for stackedNode in stack { + let transition = stackedNode == stack.first ? SystemTransition.set: SystemTransition.push + scenes += try staticScenes(fromNode: stackedNode, transition: transition) + } + default: + if let presentedNode = node.presentedViewController { + scenes += try staticScenes(fromNode: presentedNode, transition: SystemTransition.present) + } + } + + return scenes + } + + private var scripts = [Script]() + + private lazy var performanceQueue = { () -> OperationQueue in + let q = OperationQueue() + q.underlyingQueue = DispatchQueue.main + q.name = "StoryKit.performanceQueue" + q.qualityOfService = .userInitiated + q.maxConcurrentOperationCount = 1 + return q + }() + private var currentPerformance: Storyish? +} + +//MARK: URL Handling + +public extension Stage { + public func perform(url: URL, animated: Bool = true, completion: Ovation? = nil ) { + guard let story = story(matchingURL: url) else { + completion?(nil) + return + } + perform(story, animated: animated, completion: completion) + } + + func story(matchingURL url: URL) -> Story? { + // Starting with url.pathComponents, for each component: + // - look at each script's corresponding path scene (not all scenes contribute to the path, such as junction scenes) for each registered script + // - match match each scene to the current component, for input captures, match to any data in the component (e.g. /123/) + // Do this breadth first and reduce: slice off the first component, and return scripts with matching scenes at that depth, then slice off the next components one level deeper anre repeat until no more components exist. + // See if you have a match (there will only be one or none because url uniqueness is based on segments that resolve to a leaf) + // + // Example: + // Matching URL "/foo/bar/bat/bing" against scripts like (/foo, /foo/bar/bam/bappo, /foo/bar/bat/zing, /foo/bar/bat/bing) will reduce the candidate scripts this way until there is only one: + // foo: - - - - - - - + // bar: - - - - - + // bat: - - - + // bing: - + let components = url.pathComponents + print(components) + let matchingScripts: [Script] = url.pathComponents.enumerated().reduce(Array