diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100755 index 0000000..90195f1 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,96 @@ +swiftlint_version: 0.43.1 + +excluded: # paths to ignore during linting. Takes precedence over `included`. + - Pods + +analyzer_rules: # Rules run by `swiftlint analyze` (experimental) + - unused_declaration + - unused_import + +deployment_target: + iOS_deployment_target: 10.0 + +closure_body_length: + warning: 30 + error: 30 + +identifier_name: + max_length: 150 + +file_length: + warning: 1500 + error: 1500 + #ignore_comment_only_lines: true + +function_body_length: + warning: 200 + error: 200 + +function_parameter_count: + warning: 8 + error: 8 + +line_length: + warning: 1000 + error: 1000 + +type_body_length: + warning: 1000 + error: 1000 + +type_name: + max_length: 150 + +cyclomatic_complexity: + warning: 30 + error: 30 + +opt_in_rules: + - closure_body_length + # - closure_end_indentation # disabled, because xcode's block indentation depends on `[weak self]` + - closure_spacing + - contains_over_filter_count + - contains_over_filter_is_empty + - discouraged_optional_boolean + - duplicate_imports + - empty_collection_literal + - empty_count + - empty_string + - explicit_init + - fatal_error_message + # - file_name # disabled, because results are not consistent + # - file_header + - first_where + - force_unwrapping + - identical_operands + # - indentation_width # disabled, because multiline arguments are not recognized properly + - inert_defer + - last_where + - legacy_random + - let_var_whitespace + # - multiline_arguments + - multiline_parameters + - multiple_closures_with_trailing_closure + - no_space_in_method_call + # - object_literal + - operator_usage_whitespace + - optional_enum_case_matching + - prefer_self_type_over_type_of_self + - prefixed_toplevel_constant + - private_action + - private_over_fileprivate + - prohibited_super_call + - reduce_into + - redundant_nil_coalescing + - single_test_class + - sorted_first_last + # - sorted_imports + - strict_fileprivate + - strong_iboutlet + - toggle_bool + # - type_contents_order # https://realm.github.io/SwiftLint/type_contents_order.html + # - trailing_closure + - unowned_variable_capture + - unused_setter_value + - vertical_parameter_alignment_on_call + - yoda_condition diff --git a/ContainerViewController.xcworkspace/contents.xcworkspacedata b/ContainerViewController.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..64bb64f --- /dev/null +++ b/ContainerViewController.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/ContainerViewController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ContainerViewController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ContainerViewController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ContainerViewController.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ContainerViewController.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ContainerViewController.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ContainerViewController_Example.xcodeproj/project.pbxproj b/ContainerViewController_Example.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a2305fd --- /dev/null +++ b/ContainerViewController_Example.xcodeproj/project.pbxproj @@ -0,0 +1,470 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 17C38061288EC55100D3EE9F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C38060288EC55100D3EE9F /* AppDelegate.swift */; }; + 17C38065288EC55100D3EE9F /* ExampleContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C38064288EC55100D3EE9F /* ExampleContainerViewController.swift */; }; + 17C38068288EC55100D3EE9F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 17C38066288EC55100D3EE9F /* Main.storyboard */; }; + 17C3806A288EC55200D3EE9F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 17C38069288EC55200D3EE9F /* Assets.xcassets */; }; + 17C3806D288EC55200D3EE9F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 17C3806B288EC55200D3EE9F /* LaunchScreen.storyboard */; }; + 17C38075288EC7D100D3EE9F /* ContainerViewController_Framework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17C38074288EC7D100D3EE9F /* ContainerViewController_Framework.framework */; }; + 17C38076288EC7D100D3EE9F /* ContainerViewController_Framework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 17C38074288EC7D100D3EE9F /* ContainerViewController_Framework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 3E7A0C014C7A37B3190B945C /* Pods_ContainerViewController_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F98515826E1D6F42767E93A3 /* Pods_ContainerViewController_Example.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 17C38077288EC7D100D3EE9F /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 17C38076288EC7D100D3EE9F /* ContainerViewController_Framework.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 17C3805D288EC55100D3EE9F /* ContainerViewController_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ContainerViewController_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 17C38060288EC55100D3EE9F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 17C38064288EC55100D3EE9F /* ExampleContainerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleContainerViewController.swift; sourceTree = ""; }; + 17C38067288EC55100D3EE9F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 17C38069288EC55200D3EE9F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 17C3806C288EC55200D3EE9F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 17C3806E288EC55200D3EE9F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 17C38074288EC7D100D3EE9F /* ContainerViewController_Framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = ContainerViewController_Framework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 4374E9459DC83772328D328C /* Pods-ContainerViewController_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ContainerViewController_Example.release.xcconfig"; path = "Target Support Files/Pods-ContainerViewController_Example/Pods-ContainerViewController_Example.release.xcconfig"; sourceTree = ""; }; + 889F4EC2F1C934B1A8D30543 /* Pods-ContainerViewController_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ContainerViewController_Example.debug.xcconfig"; path = "Target Support Files/Pods-ContainerViewController_Example/Pods-ContainerViewController_Example.debug.xcconfig"; sourceTree = ""; }; + F98515826E1D6F42767E93A3 /* Pods_ContainerViewController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ContainerViewController_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 17C3805A288EC55100D3EE9F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 17C38075288EC7D100D3EE9F /* ContainerViewController_Framework.framework in Frameworks */, + 3E7A0C014C7A37B3190B945C /* Pods_ContainerViewController_Example.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 17C38054288EC55100D3EE9F = { + isa = PBXGroup; + children = ( + 17C3805F288EC55100D3EE9F /* ContainerViewController_Example */, + 17C3805E288EC55100D3EE9F /* Products */, + DF7B50AFB5296989518780D0 /* Pods */, + 89BE62480D4D85482C78ED26 /* Frameworks */, + ); + sourceTree = ""; + }; + 17C3805E288EC55100D3EE9F /* Products */ = { + isa = PBXGroup; + children = ( + 17C3805D288EC55100D3EE9F /* ContainerViewController_Example.app */, + ); + name = Products; + sourceTree = ""; + }; + 17C3805F288EC55100D3EE9F /* ContainerViewController_Example */ = { + isa = PBXGroup; + children = ( + 17C38060288EC55100D3EE9F /* AppDelegate.swift */, + 17C38064288EC55100D3EE9F /* ExampleContainerViewController.swift */, + 17C38066288EC55100D3EE9F /* Main.storyboard */, + 17C38069288EC55200D3EE9F /* Assets.xcassets */, + 17C3806B288EC55200D3EE9F /* LaunchScreen.storyboard */, + 17C3806E288EC55200D3EE9F /* Info.plist */, + ); + path = ContainerViewController_Example; + sourceTree = ""; + }; + 89BE62480D4D85482C78ED26 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 17C38074288EC7D100D3EE9F /* ContainerViewController_Framework.framework */, + F98515826E1D6F42767E93A3 /* Pods_ContainerViewController_Example.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + DF7B50AFB5296989518780D0 /* Pods */ = { + isa = PBXGroup; + children = ( + 889F4EC2F1C934B1A8D30543 /* Pods-ContainerViewController_Example.debug.xcconfig */, + 4374E9459DC83772328D328C /* Pods-ContainerViewController_Example.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 17C3805C288EC55100D3EE9F /* ContainerViewController_Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 17C38071288EC55200D3EE9F /* Build configuration list for PBXNativeTarget "ContainerViewController_Example" */; + buildPhases = ( + BA83E1114F947B914E61E222 /* [CP] Check Pods Manifest.lock */, + 17C380BB288ED4A900D3EE9F /* Swiftlint script */, + 17C38059288EC55100D3EE9F /* Sources */, + 17C3805A288EC55100D3EE9F /* Frameworks */, + 17C3805B288EC55100D3EE9F /* Resources */, + 17C38077288EC7D100D3EE9F /* Embed Frameworks */, + 59B0ED842ED2EC00868533AB /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ContainerViewController_Example; + productName = ContainerViewController_Example; + productReference = 17C3805D288EC55100D3EE9F /* ContainerViewController_Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 17C38055288EC55100D3EE9F /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1330; + LastUpgradeCheck = 1330; + TargetAttributes = { + 17C3805C288EC55100D3EE9F = { + CreatedOnToolsVersion = 13.3.1; + }; + }; + }; + buildConfigurationList = 17C38058288EC55100D3EE9F /* Build configuration list for PBXProject "ContainerViewController_Example" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 17C38054288EC55100D3EE9F; + productRefGroup = 17C3805E288EC55100D3EE9F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 17C3805C288EC55100D3EE9F /* ContainerViewController_Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 17C3805B288EC55100D3EE9F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 17C3806D288EC55200D3EE9F /* LaunchScreen.storyboard in Resources */, + 17C3806A288EC55200D3EE9F /* Assets.xcassets in Resources */, + 17C38068288EC55100D3EE9F /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 17C380BB288ED4A900D3EE9F /* Swiftlint script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Swiftlint script"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "#debug log\nset -x\n\n${PODS_ROOT}/SwiftLint/swiftlint\n"; + }; + 59B0ED842ED2EC00868533AB /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-ContainerViewController_Example/Pods-ContainerViewController_Example-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-ContainerViewController_Example/Pods-ContainerViewController_Example-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-ContainerViewController_Example/Pods-ContainerViewController_Example-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + BA83E1114F947B914E61E222 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ContainerViewController_Example-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 17C38059288EC55100D3EE9F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 17C38065288EC55100D3EE9F /* ExampleContainerViewController.swift in Sources */, + 17C38061288EC55100D3EE9F /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 17C38066288EC55100D3EE9F /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 17C38067288EC55100D3EE9F /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 17C3806B288EC55200D3EE9F /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 17C3806C288EC55200D3EE9F /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 17C3806F288EC55200D3EE9F /* 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++17"; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + 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; + COPY_PHASE_STRIP = NO; + 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 = 15.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 17C38070288EC55200D3EE9F /* 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++17"; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + 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; + COPY_PHASE_STRIP = NO; + 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 = 15.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 17C38072288EC55200D3EE9F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 889F4EC2F1C934B1A8D30543 /* Pods-ContainerViewController_Example.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = MW2UF479VW; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = ContainerViewController_Example/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.shakuro.ContainerViewController-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 17C38073288EC55200D3EE9F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 4374E9459DC83772328D328C /* Pods-ContainerViewController_Example.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = MW2UF479VW; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = ContainerViewController_Example/Info.plist; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; + INFOPLIST_KEY_UIMainStoryboardFile = Main; + INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.shakuro.ContainerViewController-Example"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 17C38058288EC55100D3EE9F /* Build configuration list for PBXProject "ContainerViewController_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 17C3806F288EC55200D3EE9F /* Debug */, + 17C38070288EC55200D3EE9F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 17C38071288EC55200D3EE9F /* Build configuration list for PBXNativeTarget "ContainerViewController_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 17C38072288EC55200D3EE9F /* Debug */, + 17C38073288EC55200D3EE9F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 17C38055288EC55100D3EE9F /* Project object */; +} diff --git a/ContainerViewController_Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ContainerViewController_Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ContainerViewController_Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ContainerViewController_Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ContainerViewController_Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ContainerViewController_Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ContainerViewController_Example/AppDelegate.swift b/ContainerViewController_Example/AppDelegate.swift new file mode 100644 index 0000000..c1eb5dc --- /dev/null +++ b/ContainerViewController_Example/AppDelegate.swift @@ -0,0 +1,17 @@ +// +// Copyright (c) 2022 Shakuro (https://shakuro.com/) +// +// + +import UIKit + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + return true + } + +} diff --git a/ContainerViewController_Example/Assets.xcassets/AccentColor.colorset/Contents.json b/ContainerViewController_Example/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/ContainerViewController_Example/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ContainerViewController_Example/Assets.xcassets/AppIcon.appiconset/Contents.json b/ContainerViewController_Example/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..5a3257a --- /dev/null +++ b/ContainerViewController_Example/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,93 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ContainerViewController_Example/Assets.xcassets/Contents.json b/ContainerViewController_Example/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ContainerViewController_Example/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ContainerViewController_Example/Base.lproj/LaunchScreen.storyboard b/ContainerViewController_Example/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..865e932 --- /dev/null +++ b/ContainerViewController_Example/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ContainerViewController_Example/Base.lproj/Main.storyboard b/ContainerViewController_Example/Base.lproj/Main.storyboard new file mode 100644 index 0000000..2978c14 --- /dev/null +++ b/ContainerViewController_Example/Base.lproj/Main.storyboard @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ContainerViewController_Example/ExampleContainerViewController.swift b/ContainerViewController_Example/ExampleContainerViewController.swift new file mode 100644 index 0000000..1782ad2 --- /dev/null +++ b/ContainerViewController_Example/ExampleContainerViewController.swift @@ -0,0 +1,71 @@ +// +// Copyright (c) 2022 Shakuro (https://shakuro.com/) +// +// + +import UIKit +import ContainerViewController_Framework +import Shakuro_CommonTypes + +class ExampleContainerViewController: ContainerViewController { + + @IBOutlet private var segmentedcontrol: UISegmentedControl! + + override func viewDidLoad() { + super.viewDidLoad() + title = NSLocalizedString("Container View Controller", comment: "") + let initialController = UIViewController() + initialController.view.backgroundColor = UIColor.random() + present(initialController, style: .fade, animated: false) + } + + override func willPresentViewController(_ controller: UIViewController, animated: Bool) { + } + + override func didPresentViewController(_ controller: UIViewController, animated: Bool) { + guard let actualController = currentViewController else { + return + } + segmentedcontrol.tintColor = actualController.view.backgroundColor + } + + @IBAction private func segmentedControlValueChanged(_ sender: UISegmentedControl) { + guard sender.selectedSegmentIndex != UISegmentedControl.noSegment else { + return + } + let nextController = UIViewController() + nextController.view.backgroundColor = UIColor.random() + let transition: TransitionStyle + switch sender.selectedSegmentIndex { + case 0: + transition = .push + case 1: + transition = .pop + case 2: + transition = .fade + case 3: + transition = .custom(animator: ExampleAnimator()) + default: + fatalError("Unknown UISegmentedControl index") + } + present(nextController, style: transition, animated: true) + } + +} + +private struct ExampleAnimator: ContainerViewControllerTransitionAnimator { + + func animate(fromView: UIView?, toView: UIView, containerView: UIView, didFinish: @escaping () -> Void) { + guard let actualFrom = fromView else { + didFinish() + return + } + toView.transform = CGAffineTransform(translationX: 0, y: -toView.bounds.size.height) + UIView.animate(withDuration: 0.6, delay: 0.0, options: [], animations: { + actualFrom.transform = CGAffineTransform(translationX: 0, y: actualFrom.bounds.size.height) + toView.transform = CGAffineTransform.identity + }, completion: { (_) in + didFinish() + }) + } +} diff --git a/ContainerViewController_Example/Info.plist b/ContainerViewController_Example/Info.plist new file mode 100644 index 0000000..0c67376 --- /dev/null +++ b/ContainerViewController_Example/Info.plist @@ -0,0 +1,5 @@ + + + + + diff --git a/ContainerViewController_Framework.xcodeproj/project.pbxproj b/ContainerViewController_Framework.xcodeproj/project.pbxproj new file mode 100644 index 0000000..98f69fc --- /dev/null +++ b/ContainerViewController_Framework.xcodeproj/project.pbxproj @@ -0,0 +1,414 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 17C38046288EC2CB00D3EE9F /* ContainerViewController_Framework.h in Headers */ = {isa = PBXBuildFile; fileRef = 17C38045288EC2CB00D3EE9F /* ContainerViewController_Framework.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 17C38050288EC49200D3EE9F /* Shakuro.ContainerViewController.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 17C3804F288EC49200D3EE9F /* Shakuro.ContainerViewController.podspec */; }; + 17C38053288EC50000D3EE9F /* ContainerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 17C38052288EC50000D3EE9F /* ContainerViewController.swift */; }; + 68D6C9CDD8167AD76393B262 /* Pods_ContainerViewController_Framework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA24F266759B1A9F578657C4 /* Pods_ContainerViewController_Framework.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 17C38042288EC2CB00D3EE9F /* ContainerViewController_Framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ContainerViewController_Framework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 17C38045288EC2CB00D3EE9F /* ContainerViewController_Framework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ContainerViewController_Framework.h; sourceTree = ""; }; + 17C3804C288EC35E00D3EE9F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 17C3804D288EC3C500D3EE9F /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 17C3804E288EC3C500D3EE9F /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = ""; }; + 17C3804F288EC49200D3EE9F /* Shakuro.ContainerViewController.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = Shakuro.ContainerViewController.podspec; sourceTree = ""; }; + 17C38052288EC50000D3EE9F /* ContainerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContainerViewController.swift; sourceTree = ""; }; + 585F1A63154CA2A1CF4FEB5D /* Pods-ContainerViewController_Framework.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ContainerViewController_Framework.debug.xcconfig"; path = "Target Support Files/Pods-ContainerViewController_Framework/Pods-ContainerViewController_Framework.debug.xcconfig"; sourceTree = ""; }; + CA24F266759B1A9F578657C4 /* Pods_ContainerViewController_Framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_ContainerViewController_Framework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DF068EF302476A93FC6F0059 /* Pods-ContainerViewController_Framework.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ContainerViewController_Framework.release.xcconfig"; path = "Target Support Files/Pods-ContainerViewController_Framework/Pods-ContainerViewController_Framework.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 17C3803F288EC2CB00D3EE9F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 68D6C9CDD8167AD76393B262 /* Pods_ContainerViewController_Framework.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 17C38038288EC2CB00D3EE9F = { + isa = PBXGroup; + children = ( + 17C3804E288EC3C500D3EE9F /* LICENSE.md */, + 17C3804D288EC3C500D3EE9F /* README.md */, + 17C3804F288EC49200D3EE9F /* Shakuro.ContainerViewController.podspec */, + 17C38044288EC2CB00D3EE9F /* ContainerViewController_Framework */, + 17C38051288EC50000D3EE9F /* Source */, + 17C38043288EC2CB00D3EE9F /* Products */, + 3915B8A06222C8611B933DDA /* Pods */, + B9C1A582A6FC9719DD0269D7 /* Frameworks */, + ); + sourceTree = ""; + }; + 17C38043288EC2CB00D3EE9F /* Products */ = { + isa = PBXGroup; + children = ( + 17C38042288EC2CB00D3EE9F /* ContainerViewController_Framework.framework */, + ); + name = Products; + sourceTree = ""; + }; + 17C38044288EC2CB00D3EE9F /* ContainerViewController_Framework */ = { + isa = PBXGroup; + children = ( + 17C38045288EC2CB00D3EE9F /* ContainerViewController_Framework.h */, + 17C3804C288EC35E00D3EE9F /* Info.plist */, + ); + path = ContainerViewController_Framework; + sourceTree = ""; + }; + 17C38051288EC50000D3EE9F /* Source */ = { + isa = PBXGroup; + children = ( + 17C38052288EC50000D3EE9F /* ContainerViewController.swift */, + ); + path = Source; + sourceTree = ""; + }; + 3915B8A06222C8611B933DDA /* Pods */ = { + isa = PBXGroup; + children = ( + 585F1A63154CA2A1CF4FEB5D /* Pods-ContainerViewController_Framework.debug.xcconfig */, + DF068EF302476A93FC6F0059 /* Pods-ContainerViewController_Framework.release.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; + B9C1A582A6FC9719DD0269D7 /* Frameworks */ = { + isa = PBXGroup; + children = ( + CA24F266759B1A9F578657C4 /* Pods_ContainerViewController_Framework.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 17C3803D288EC2CB00D3EE9F /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 17C38046288EC2CB00D3EE9F /* ContainerViewController_Framework.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 17C38041288EC2CB00D3EE9F /* ContainerViewController_Framework */ = { + isa = PBXNativeTarget; + buildConfigurationList = 17C38049288EC2CB00D3EE9F /* Build configuration list for PBXNativeTarget "ContainerViewController_Framework" */; + buildPhases = ( + F84ACF1095F4E8F2AE9794E1 /* [CP] Check Pods Manifest.lock */, + 17C3803D288EC2CB00D3EE9F /* Headers */, + 17C3803E288EC2CB00D3EE9F /* Sources */, + 17C3803F288EC2CB00D3EE9F /* Frameworks */, + 17C38040288EC2CB00D3EE9F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ContainerViewController_Framework; + productName = ContainerViewController_Framework; + productReference = 17C38042288EC2CB00D3EE9F /* ContainerViewController_Framework.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 17C38039288EC2CB00D3EE9F /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastUpgradeCheck = 1330; + TargetAttributes = { + 17C38041288EC2CB00D3EE9F = { + CreatedOnToolsVersion = 13.3.1; + }; + }; + }; + buildConfigurationList = 17C3803C288EC2CB00D3EE9F /* Build configuration list for PBXProject "ContainerViewController_Framework" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 17C38038288EC2CB00D3EE9F; + productRefGroup = 17C38043288EC2CB00D3EE9F /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 17C38041288EC2CB00D3EE9F /* ContainerViewController_Framework */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 17C38040288EC2CB00D3EE9F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 17C38050288EC49200D3EE9F /* Shakuro.ContainerViewController.podspec in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + F84ACF1095F4E8F2AE9794E1 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-ContainerViewController_Framework-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 17C3803E288EC2CB00D3EE9F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 17C38053288EC50000D3EE9F /* ContainerViewController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 17C38047288EC2CB00D3EE9F /* 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++17"; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + 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; + 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.0; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = 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; + }; + 17C38048288EC2CB00D3EE9F /* 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++17"; + 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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + 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; + 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.0; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 17C3804A288EC2CB00D3EE9F /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 585F1A63154CA2A1CF4FEB5D /* Pods-ContainerViewController_Framework.debug.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = MW2UF479VW; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = ContainerViewController_Framework/Info.plist; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.shakuro.ContainerViewController-Framework"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 17C3804B288EC2CB00D3EE9F /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DF068EF302476A93FC6F0059 /* Pods-ContainerViewController_Framework.release.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = MW2UF479VW; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = NO; + INFOPLIST_FILE = ContainerViewController_Framework/Info.plist; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.shakuro.ContainerViewController-Framework"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 17C3803C288EC2CB00D3EE9F /* Build configuration list for PBXProject "ContainerViewController_Framework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 17C38047288EC2CB00D3EE9F /* Debug */, + 17C38048288EC2CB00D3EE9F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 17C38049288EC2CB00D3EE9F /* Build configuration list for PBXNativeTarget "ContainerViewController_Framework" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 17C3804A288EC2CB00D3EE9F /* Debug */, + 17C3804B288EC2CB00D3EE9F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 17C38039288EC2CB00D3EE9F /* Project object */; +} diff --git a/ContainerViewController_Framework.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ContainerViewController_Framework.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ContainerViewController_Framework.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ContainerViewController_Framework.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ContainerViewController_Framework.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ContainerViewController_Framework.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ContainerViewController_Framework/ContainerViewController_Framework.h b/ContainerViewController_Framework/ContainerViewController_Framework.h new file mode 100644 index 0000000..277bba5 --- /dev/null +++ b/ContainerViewController_Framework/ContainerViewController_Framework.h @@ -0,0 +1,18 @@ +// +// ContainerViewController_Framework.h +// ContainerViewController_Framework +// +// Created by shakuro on 25.07.2022. +// + +#import + +//! Project version number for ContainerViewController_Framework. +FOUNDATION_EXPORT double ContainerViewController_FrameworkVersionNumber; + +//! Project version string for ContainerViewController_Framework. +FOUNDATION_EXPORT const unsigned char ContainerViewController_FrameworkVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/ContainerViewController_Framework/Info.plist b/ContainerViewController_Framework/Info.plist new file mode 100644 index 0000000..9bcb244 --- /dev/null +++ b/ContainerViewController_Framework/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..08b7c16 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Shakuro (https://shakuro.com/) + +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/Podfile b/Podfile new file mode 100644 index 0000000..1b7a10b --- /dev/null +++ b/Podfile @@ -0,0 +1,17 @@ +source 'https://github.com/CocoaPods/Specs.git' + +platform :ios, '11.0' + +use_frameworks! + +workspace 'ContainerViewController' + +target 'ContainerViewController_Framework' do + project 'ContainerViewController_Framework.xcodeproj' +end + +target 'ContainerViewController_Example' do + project 'ContainerViewController_Example.xcodeproj' + pod 'Shakuro.CommonTypes', '1.1.2' + pod 'SwiftLint', '0.43.1' +end diff --git a/Podfile.lock b/Podfile.lock new file mode 100644 index 0000000..1108cb2 --- /dev/null +++ b/Podfile.lock @@ -0,0 +1,20 @@ +PODS: + - Shakuro.CommonTypes (1.1.2) + - SwiftLint (0.43.1) + +DEPENDENCIES: + - Shakuro.CommonTypes (= 1.1.2) + - SwiftLint (= 0.43.1) + +SPEC REPOS: + https://github.com/CocoaPods/Specs.git: + - Shakuro.CommonTypes + - SwiftLint + +SPEC CHECKSUMS: + Shakuro.CommonTypes: d7145227330b0033eaecb2dd89a29cfe28b7c547 + SwiftLint: 99f82d07b837b942dd563c668de129a03fc3fb52 + +PODFILE CHECKSUM: 2d1ec51fa1f469fe1d5cf873e85b30563b67ef2b + +COCOAPODS: 1.11.3 diff --git a/README.md b/README.md new file mode 100644 index 0000000..682a2d5 --- /dev/null +++ b/README.md @@ -0,0 +1,51 @@ +![Shakuro ContainerViewController](title_image.png) +

+# ContainerViewController +![Version](https://img.shields.io/badge/version-1.0.0-blue.svg) +![Platform](https://img.shields.io/badge/platform-iOS-lightgrey.svg) +![License MIT](https://img.shields.io/badge/license-MIT-green.svg) + +- [Requirements](#requirements) +- [Installation](#installation) +- [Usage](#usage) +- [License](#license) + +## Requirements + +- iOS 11.0+ +- Xcode 11.0+ +- Swift 5.0+ + +## Installation + +### CocoaPods + +To integrate ContainerViewController into your Xcode project with CocoaPods, specify it in your `Podfile`: + +```ruby +pod 'Shakuro.ContainerViewController' +``` + +Then, run the following command: + +```bash +$ pod install +``` + +### Manually + +If you prefer not to use CocoaPods, you can integrate Shakuro.ContainerViewController simply by copying it to your project. + +## Usage + +Have a look at the [ContainerViewController_Example](https://github.com/shakurocom/ContainerViewController/tree/master/ContainerViewController_Example) + +## License + +Shakuro.ContainerViewController is released under the MIT license. [See LICENSE](https://github.com/shakurocom/ContainerViewController/blob/master/LICENSE.md) for details. + +## Give it a try and reach us + +Star this tool if you like it, it will help us grow and add new useful things. +Feel free to reach out and hire our team to develop a mobile or web project for you. + diff --git a/Shakuro.ContainerViewController.podspec b/Shakuro.ContainerViewController.podspec new file mode 100644 index 0000000..7266f33 --- /dev/null +++ b/Shakuro.ContainerViewController.podspec @@ -0,0 +1,14 @@ +Pod::Spec.new do |s| + + s.name = 'Shakuro.ContainerViewController' + s.version = '1.0.0' + s.summary = 'ContainerViewController' + s.homepage = 'https://github.com/shakurocom/ContainerViewController' + s.license = { :type => "MIT", :file => "LICENSE.md" } + s.authors = {'apopov1988' => 'apopov@shakuro.com', 'wwwpix' => 'spopov@shakuro.com'} + s.source = { :git => 'https://github.com/shakurocom/ContainerViewController.git', :tag => s.version } + s.swift_versions = ['5.1', '5.2', '5.3', '5.4', '5.5', '5.6'] + s.source_files = 'Source/*' + s.ios.deployment_target = '11.0' + +end diff --git a/Source/ContainerViewController.swift b/Source/ContainerViewController.swift new file mode 100644 index 0000000..8ad20f7 --- /dev/null +++ b/Source/ContainerViewController.swift @@ -0,0 +1,189 @@ +// +// Copyright (c) 2019 Shakuro (https://shakuro.com/) +// +// + +import UIKit + +public extension UIViewController { + + /// If the recipient is a child of a ContainerViewController, this property holds the view controller it is contained in. + var containerViewController: ContainerViewController? { + return parent as? ContainerViewController + } +} + +public protocol ContainerViewControllerPresenting: AnyObject { + func present(_ controller: UIViewController, style: ContainerViewController.TransitionStyle, animated: Bool) +} + +/// Custom Animator support +public protocol ContainerViewControllerTransitionAnimator { + + /// Will be called by the ContainerViewController during animated transition + /// + /// - Parameters: + /// - fromView: Old content view or nil + /// - toView: New content view to display + /// - containerView: The container view where content view is placed + /// - didFinish: A closure to be executed when the transition ends. + func animate(fromView: UIView?, toView: UIView, containerView: UIView, didFinish: @escaping () -> Void) +} + +/// A container view controller with animated transition support +open class ContainerViewController: UIViewController, ContainerViewControllerPresenting { + + /// The type of transition animation + public enum TransitionStyle { + case push + case pop + case fade + case custom(animator: ContainerViewControllerTransitionAnimator) + } + + /// The view controller that is presented by this view controller or nil + public private(set) var currentViewController: UIViewController? + + /// Indicates that the controller is currently on the screen + public private(set) var isOnScreen: Bool = false + + /// The super view for currentViewController.view + @IBOutlet public private(set) var containerView: UIView! + + open override func viewDidLoad() { + super.viewDidLoad() + view.clipsToBounds = true + containerView.clipsToBounds = true + } + + open override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + isOnScreen = true + } + + open override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + isOnScreen = false + } + + /// Performs transition to the new view controller + /// + /// - Parameters: + /// - controller: The view controller that will be presented + /// - style: The type of transition animation + /// - animated: Perform or do not perform animation during transition + public final func present(_ newController: UIViewController, style: TransitionStyle, animated: Bool) { + guard newController !== currentViewController else { + return + } + willPresentViewController(newController, animated: animated) + let actuallyOnScreen: Bool = isOnScreen + let oldController: UIViewController? = currentViewController + currentViewController = newController + + oldController?.willMove(toParent: nil) + if actuallyOnScreen { + oldController?.beginAppearanceTransition(false, animated: animated) + } + addChild(newController) + if actuallyOnScreen { + newController.beginAppearanceTransition(true, animated: animated) + } + + let fromView: UIView? = oldController?.view + + let toView: UIView = newController.view + toView.translatesAutoresizingMaskIntoConstraints = true + toView.frame = containerView.bounds + toView.autoresizingMask = [.flexibleHeight, .flexibleWidth] + containerView.addSubview(toView) + + view.isUserInteractionEnabled = false + let finishTransition: () -> Void = { + if let actualOld: UIViewController = oldController { + actualOld.view.removeFromSuperview() + if actuallyOnScreen { + actualOld.endAppearanceTransition() + } + actualOld.removeFromParent() + } + if actuallyOnScreen { + newController.endAppearanceTransition() + } + newController.didMove(toParent: self) + self.view.isUserInteractionEnabled = true + self.didPresentViewController(newController, animated: animated) + } + + if animated { + switch (style, fromView) { + case (.push, .some(let actualFromView)): + animatePushPop(fromView: actualFromView, toView: toView, push: true, didFinish: finishTransition) + case (.pop, .some(let actualFromView)): + animatePushPop(fromView: actualFromView, toView: toView, push: false, didFinish: finishTransition) + case (.fade, _): + animateFade(fromView: nil, toView: toView, didFinish: finishTransition) + case (.custom(let animator), _): + animator.animate(fromView: fromView, toView: toView, containerView: containerView, didFinish: finishTransition) + default: + finishTransition() + } + } else { + finishTransition() + } + } + + // MARK: - Override + + /// Will be performed directly before transition + /// + /// - Parameters: + /// - controller: The view controller that will be presented + /// - animated: true if transition is animated, false otherwise + open func willPresentViewController(_ controller: UIViewController, animated: Bool) {} + + /// Will be performed when the transition ends. + /// + /// - Parameters: + /// - controller: The view controller that will be presented + /// - animated: true if transition was animated, false otherwise + open func didPresentViewController(_ controller: UIViewController, animated: Bool) {} + +} + +// MARK: - Private + +private extension ContainerViewController { + + func animatePushPop(fromView: UIView, toView: UIView, push: Bool, didFinish: @escaping () -> Void) { + let contentSizeWidth: CGFloat = containerView.bounds.size.width + let toViewTransform: CGAffineTransform + let fromViewTransform: CGAffineTransform + if push { + toViewTransform = CGAffineTransform(translationX: contentSizeWidth, y: 0) + fromViewTransform = CGAffineTransform(translationX: -contentSizeWidth * 0.3, y: 0) + } else { + toViewTransform = CGAffineTransform(translationX: -contentSizeWidth * 0.3, y: 0) + fromViewTransform = CGAffineTransform(translationX: contentSizeWidth, y: 0) + containerView.sendSubviewToBack(toView) + } + toView.transform = toViewTransform + UIView.animate(withDuration: 0.33, delay: 0.0, options: [.curveEaseOut], animations: { + toView.transform = CGAffineTransform.identity + fromView.transform = fromViewTransform + }, completion: { (_) in + fromView.transform = CGAffineTransform.identity + didFinish() + }) + } + + func animateFade(fromView: UIView?, toView: UIView, didFinish: @escaping () -> Void) { + toView.alpha = 0.0 + UIView.animate(withDuration: 0.25, animations: { + fromView?.alpha = 0.0 + toView.alpha = 1.0 + }, completion: { (_) in + didFinish() + }) + } +} diff --git a/title_image.png b/title_image.png new file mode 100644 index 0000000..a74b100 Binary files /dev/null and b/title_image.png differ