diff --git a/Example/Base.lproj/Main.storyboard b/Example/Base.lproj/Main.storyboard index 5456038..f1168be 100644 --- a/Example/Base.lproj/Main.storyboard +++ b/Example/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -15,8 +15,8 @@ - + @@ -43,13 +43,13 @@ - + + @@ -259,7 +260,6 @@ - @@ -312,7 +312,7 @@ + @@ -662,7 +683,6 @@ - diff --git a/Package.swift b/Package.swift index 21eb973..daa56f8 100644 --- a/Package.swift +++ b/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "SideMenu", platforms: [ - .iOS(.v9) + .iOS(.v11) ], products: [ // Products define the executables and libraries produced by a package, and make them visible to other packages. diff --git a/README.md b/README.md index f38b885..e60559b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,3 @@ -# ![](https://github.com/kukushi/SideMenu/blob/develop/Images/Logo.png?raw=true) - [![Version](https://img.shields.io/cocoapods/v/SideMenuSwift.svg?style=flat-square)](http://cocoapods.org/pods/SideMenuSwift) ![Swift5](https://img.shields.io/badge/Swift-5.0-orange.svg?style=flat%22) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square)](https://github.com/Carthage/Carthage) @@ -26,12 +24,12 @@ Besides all the features a *Side Menu* should have, it supports: Menu Position / Status Menu Behavior -| Above + None | Below + Slide | -| --- | --- | +| Above + None | Below + Slide | +| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | | ![](https://raw.githubusercontent.com/kukushi/SideMenu/master/Images/Above%2BNone.gif) | ![](https://raw.githubusercontent.com/kukushi/SideMenu/master/Images/Below%2BSlide.gif) | -| SideBySide + Fade | SideBySide + HideOnMenu | -| --- | --- | +| SideBySide + Fade | SideBySide + HideOnMenu | +| ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | ![](https://raw.githubusercontent.com/kukushi/SideMenu/master/Images/SideBySide%2BFade.gif) | ![](https://raw.githubusercontent.com/kukushi/SideMenu/master/Images/SideBySide%2BHideOnMenu.gif) | We call the left/right view controller as the **menu** view controller, the central view controller as **content** view controller. @@ -51,6 +49,7 @@ To install `SideMenu` with [CocoaPods](http://cocoapods.org/), add the below lin pod 'SideMenuSwift' # Note it's NOT 'SideMenu' ``` + ### Carthage To install `SideMenu` with [Carthage](https://github.com/Carthage/Carthage), add the below line in your `Cartfile`: @@ -76,15 +75,15 @@ github "kukushi/SideMenu" "master" To set up `SideMenu` in storyboard: - 1. Open the view controller's *Identity inspector*. Change its **Class** to `SideMenuController` and **Module** to `SideMenuSwift`. 2. Set up the menu view controller and the initial content view controller in your Storyboard. Add a **Custom** segue from the `SideMenuController` to each of them. - - Change the menu segue's identifier to `SideMenu.Menu`, **Class** to `SideMenuSegue` and **Module** to `SideMenuSwift`. - - Change the content segue's identifier to `SideMenu.Content`, **Class** to `SideMenuSegue` and **Module** to `SideMenuSwift`. -4. (Optional) If you want to use custom segue identifier: + - Change the menu segue's identifier to `SideMenu.Menu`, **Class** to `SideMenuSegue` and **Module** to `SideMenuSwift`. + - Change the content segue's identifier to `SideMenu.Content`, **Class** to `SideMenuSegue` and **Module** to `SideMenuSwift`. +3. (Optional) If you want to use custom segue identifier: - Open the `SideMenuController`'s *Attribute inspector*. - In the **Side Menu Controller** section, modify the *Content SegueID/Menu SegueID* to the desired value and change the corresponding segue's identifier. -5. It's done. Check [this screenshot](https://github.com/kukushi/SideMenu/blob/develop/Images/StoryboardSample.png?raw=true) a for clear view. +4. It's done. Check [this screenshot](https://github.com/kukushi/SideMenu/blob/develop/Images/StoryboardSample.png?raw=true) a for clear view. + ### Programmatically @@ -109,14 +108,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate { let menuViewController = ... window = UIWindow(frame: UIScreen.main.bounds) - window?.rootViewController = SideMenuController(contentViewController: contentViewController, + window?.rootViewController = SideMenuController(contentViewController: contentViewController, menuViewController: menuViewController) - + window?.makeKeyAndVisible() return true } } ``` + Use the `sideMenuController` method which provided in `UIViewController`'s extension to get the parent `SideMenuController`: @@ -143,7 +143,7 @@ SideMenuController.preferences.basic.shouldRespectLanguageDirection = true ### Caching the Content -One of the coolest features of `SideMenu` is caching. +One of the coolest features of `SideMenu` is caching. ```swift // Cache the view controllers somewhere in your code @@ -170,7 +170,7 @@ sideMenuController?.cache(viewControllerGenerator: { self.storyboard?.instantiat ## Requirements - Xcode 10 or later -- iOS 9.0 or later +- iOS 11.0 or later ## License diff --git a/SideMenu.xcodeproj/project.pbxproj b/SideMenu.xcodeproj/project.pbxproj index a0fa445..d901f19 100644 --- a/SideMenu.xcodeproj/project.pbxproj +++ b/SideMenu.xcodeproj/project.pbxproj @@ -550,9 +550,9 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = U6N93T3598; + DEVELOPMENT_TEAM = 34PEP7YC95; INFOPLIST_FILE = Example/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -570,9 +570,9 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = U6N93T3598; + DEVELOPMENT_TEAM = 34PEP7YC95; INFOPLIST_FILE = Example/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -636,7 +636,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -694,7 +694,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; @@ -714,13 +714,13 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = U6N93T3598; + DEVELOPMENT_TEAM = 34PEP7YC95; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Sources/SideMenu/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -742,13 +742,13 @@ CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Automatic; DEFINES_MODULE = YES; - DEVELOPMENT_TEAM = U6N93T3598; + DEVELOPMENT_TEAM = 34PEP7YC95; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Sources/SideMenu/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 11.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/SideMenuSwift.podspec b/SideMenuSwift.podspec index 74be848..4f732b2 100644 --- a/SideMenuSwift.podspec +++ b/SideMenuSwift.podspec @@ -3,19 +3,18 @@ Pod::Spec.new do |s| s.name = "SideMenuSwift" s.version = "2.0.10" s.summary = "An interactive iOS side menu with rich features." - + s.description = <<-DESC SideMenuSwift is an iOS container view controller written in Swift. Its easy-to-use and supports both storyboard and code. It provides several ways to reveal the menu and animate the status bar. DESC - + s.homepage = "https://github.com/kukushi/SideMenu" s.license = "MIT" s.author = { "kukushi" => "" } - s.platform = :ios, "9.0" + s.platform = :ios, "11.0" s.source = { :git => "https://github.com/kukushi/SideMenu.git", :tag => s.version } s.source_files = "Sources/SideMenu/*.{h,m,swift}" s.swift_version = "5.0" s.requires_arc = true - + end - \ No newline at end of file diff --git a/Sources/SideMenu/SideMenuController.swift b/Sources/SideMenu/SideMenuController.swift index 4d981b2..917cb3b 100644 --- a/Sources/SideMenu/SideMenuController.swift +++ b/Sources/SideMenu/SideMenuController.swift @@ -13,14 +13,13 @@ import UIKit /// A container view controller owns a menu view controller and a content view controller. /// /// The overall architecture of SideMenuController is: -/// -/// SideMenuController -/// -/// ├── Menu View Controller -/// -/// └── Content View Controller +/// +/// SideMenuController +/// +/// ├── Menu View Controller +/// +/// └── Content View Controller open class SideMenuController: UIViewController { - /// Configure this property to change the behavior of SideMenuController; public static var preferences = Preferences() private var preferences: Preferences { @@ -64,7 +63,7 @@ open class SideMenuController: UIViewController { guard contentViewController !== oldValue && isViewLoaded && !children.contains(contentViewController) else { - return + return } if shouldCallSwitchingDelegate { @@ -155,7 +154,7 @@ open class SideMenuController: UIViewController { /// ``SideMenuController`` may be initialized from Storyboard, thus we shouldn't load the view in `loadView()`. /// As mentioned by Apple, "If you use Interface Builder to create your views and initialize the view controller, /// you must not override this method." - open override func viewDidLoad() { + override open func viewDidLoad() { super.viewDidLoad() // Setup from the IB @@ -208,7 +207,7 @@ open class SideMenuController: UIViewController { // MARK: Storyboard - open override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + override open func prepare(for segue: UIStoryboardSegue, sender: Any?) { guard let segue = segue as? SideMenuSegue, let identifier = segue.identifier else { return } @@ -259,9 +258,15 @@ open class SideMenuController: UIViewController { UIApplication.shared.beginIgnoringInteractionEvents() + let frame = self.sideMenuFrame(visibility: reveal) + if reveal{ + self.menuViewController.additionalSafeAreaInsets = UIEdgeInsets(top: -frame.origin.y, left: -frame.origin.x, bottom: 0, right: 0) + self.menuContainerView.setNeedsLayout() + } let animationClosure = { - self.menuContainerView.frame = self.sideMenuFrame(visibility: reveal) + self.menuContainerView.frame = frame self.contentContainerView.frame = self.contentFrame(visibility: reveal) + self.menuContainerView.layoutIfNeeded() if self.shouldShowShadowOnContent { self.contentContainerOverlay?.alpha = reveal ? self.preferences.animation.shadowAlpha : 0 } @@ -269,7 +274,6 @@ open class SideMenuController: UIViewController { let animationCompletionClosure: (Bool) -> Void = { finish in self.menuViewController.endAppearanceTransition() - if shouldCallDelegate { if reveal { self.delegate?.sideMenuControllerDidRevealMenu(self) @@ -301,7 +305,6 @@ open class SideMenuController: UIViewController { animationCompletionClosure(true) completion?(true) } - } private func animateMenu(with reveal: Bool, @@ -319,18 +322,18 @@ open class SideMenuController: UIViewController { initialSpringVelocity: preferences.animation.initialSpringVelocity, options: preferences.animation.options, animations: { - if shouldChangeStatusBar && shouldAnimateStatusBarChange { - self.setStatusBar(hidden: reveal) - } - - animations() - }, completion: { (finished) in - if shouldChangeStatusBar && !shouldAnimateStatusBarChange && !reveal { - self.setStatusBar(hidden: reveal) - } + if shouldChangeStatusBar && shouldAnimateStatusBarChange { + self.setStatusBar(hidden: reveal) + } - completion?(finished) - }) + animations() + }, completion: { finished in + if shouldChangeStatusBar && !shouldAnimateStatusBarChange && !reveal { + self.setStatusBar(hidden: reveal) + } + + completion?(finished) + }) } // MARK: Gesture Recognizer @@ -348,7 +351,7 @@ open class SideMenuController: UIViewController { return } - var overlay:UIView + var overlay: UIView if SideMenuController.preferences.animation.shouldAddBlurWhenRevealing { let blurEffect = UIBlurEffect(style: .light) overlay = UIVisualEffectView(effect: blurEffect) @@ -459,7 +462,7 @@ open class SideMenuController: UIViewController { movingDistance = menuWidth - menuContainerView.frame.minX } let shadowPercent = min(movingDistance / menuWidth, 1) - contentContainerOverlay?.alpha = self.preferences.animation.shadowAlpha * shadowPercent + contentContainerOverlay?.alpha = preferences.animation.shadowAlpha * shadowPercent } case .ended, .cancelled, .failed: let offset: CGFloat @@ -510,7 +513,7 @@ open class SideMenuController: UIViewController { // the navigation bar will go up as we don't expect. // So we need to manipulate the windows of status bar manually. - let behavior = self.preferences.basic.statusBarBehavior + let behavior = preferences.basic.statusBarBehavior guard let sbw = UIWindow.sb, sbw.isStatusBarHidden(with: behavior) != hidden else { return } @@ -543,12 +546,12 @@ open class SideMenuController: UIViewController { return screenshot } - open override var childForStatusBarStyle: UIViewController? { + override open var childForStatusBarStyle: UIViewController? { // Forward to the content view controller return contentViewController } - open override var childForStatusBarHidden: UIViewController? { + override open var childForStatusBarHidden: UIViewController? { return contentViewController } @@ -620,10 +623,10 @@ open class SideMenuController: UIViewController { to: viewController) #if DEBUG - if animatorFromDelegate == nil { - // swiftlint:disable:next line_length - print("[SideMenu] `setContentViewController` is called with animated while the delegate method return nil, fall back to the fade animation.") - } + if animatorFromDelegate == nil { + // swiftlint:disable:next line_length + print("[SideMenu] `setContentViewController` is called with animated while the delegate method return nil, fall back to the fade animation.") + } #endif let animator = animatorFromDelegate ?? BasicTransitionAnimator() @@ -632,7 +635,7 @@ open class SideMenuController: UIViewController { toViewController: viewController) transitionContext.isAnimated = true transitionContext.isInteractive = false - transitionContext.completion = { finish in + transitionContext.completion = { _ in self.unload(self.contentViewController) self.shouldCallSwitchingDelegate = false @@ -713,27 +716,27 @@ open class SideMenuController: UIViewController { // MARK: Orientation - open override var shouldAutorotate: Bool { + override open var shouldAutorotate: Bool { if preferences.basic.shouldUseContentSupportedOrientations { return contentViewController.shouldAutorotate } return preferences.basic.shouldAutorotate } - - open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { + + override open var supportedInterfaceOrientations: UIInterfaceOrientationMask { if preferences.basic.shouldUseContentSupportedOrientations { return contentViewController.supportedInterfaceOrientations } return preferences.basic.supportedOrientations } - open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { + override open func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { hideMenu(animated: false, completion: { _ in // Temporally hide the menu container view for smooth animation self.menuContainerView.isHidden = true coordinator.animate(alongsideTransition: { _ in self.contentContainerView.frame = self.contentFrame(visibility: self.isMenuRevealed, targetSize: size) - }, completion: { (_) in + }, completion: { _ in self.menuContainerView.isHidden = false self.menuContainerView.frame = self.sideMenuFrame(visibility: self.isMenuRevealed, targetSize: size) }) @@ -751,7 +754,7 @@ extension SideMenuController: UIGestureRecognizerDelegate { return false } - if let shouldReveal = self.delegate?.sideMenuControllerShouldRevealMenu(self) { + if let shouldReveal = delegate?.sideMenuControllerShouldRevealMenu(self) { guard shouldReveal else { return false } @@ -782,10 +785,10 @@ extension SideMenuController: UIGestureRecognizerDelegate { private func isViewControllerInsideNavigationStack(for view: UIView?) -> Bool { guard let view = view, - let viewController = view.parentViewController else { - return false + let viewController = view.parentViewController else { + return false } - + if let navigationController = viewController as? UINavigationController { return navigationController.viewControllers.count > 1 } else if let navigationController = viewController.navigationController { diff --git a/Sources/SideMenu/UIViewController+Container.swift b/Sources/SideMenu/UIViewController+Container.swift index 2947553..5e942ae 100644 --- a/Sources/SideMenu/UIViewController+Container.swift +++ b/Sources/SideMenu/UIViewController+Container.swift @@ -18,13 +18,18 @@ extension UIViewController { // `willMoveToParentViewController:` is called automatically when adding addChild(viewController) - + viewController.view.frame = view.bounds - viewController.view.translatesAutoresizingMaskIntoConstraints = true - viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] - + viewController.view.translatesAutoresizingMaskIntoConstraints = false +// viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight] + view.addSubview(viewController.view) - + NSLayoutConstraint.activate([ + viewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), + viewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), + viewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), + viewController.view.topAnchor.constraint(equalTo: view.topAnchor), + ]) viewController.didMove(toParent: self) }