Container view, Failed use delegate - ios

i wanna designed slide function.So i use container view in storyboard without any segue.there is a button in centerView to open or close leftView.but this function is written in container.swift and i don't know how to set delegate..please help me,thanks.(All codes as below)
Container.swift
import UIKit
class ContainerViewController: UIViewController,test {
var leftViewController: UIViewController? {
willSet{
if self.leftViewController != nil {
if self.leftViewController!.view != nil {
self.leftViewController!.view!.removeFromSuperview()
}
self.leftViewController!.removeFromParentViewController()
}
}
didSet{
self.view!.addSubview(self.leftViewController!.view)
self.addChildViewController(self.leftViewController!)
}
}
var rightViewController: UIViewController? {
willSet {
if self.rightViewController != nil {
if self.rightViewController!.view != nil {
self.rightViewController!.view!.removeFromSuperview()
}
self.rightViewController!.removeFromParentViewController()
}
}
didSet{
self.view!.addSubview(self.rightViewController!.view)
self.addChildViewController(self.rightViewController!)
}
}
var menuShown: Bool = false
func showMenu() {
print(__FUNCTION__,__LINE__)
UIView.animateWithDuration(0.3, animations: {
self.rightViewController!.view.frame = CGRect(x: self.view.frame.origin.x + 235, y: self.view.frame.origin.y, width: self.view.frame.width, height: self.view.frame.height)
}, completion: { (Bool) -> Void in
self.menuShown = true
})
}
func hideMenu() {
UIView.animateWithDuration(0.3, animations: {
self.rightViewController!.view.frame = CGRect(x: 0, y: self.view.frame.origin.y, width: self.view.frame.width, height: self.view.frame.height)
}, completion: { (Bool) -> Void in
self.menuShown = false
})
}
var centerView:CenterViewController!
override func viewDidLoad() {
super.viewDidLoad()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let CenterNC:UINavigationController = storyboard.instantiateViewControllerWithIdentifier("CenterNC") as! UINavigationController
let leftVC:LeftViewController = storyboard.instantiateViewControllerWithIdentifier("LeftVC") as! LeftViewController
centerView = storyboard.instantiateViewControllerWithIdentifier("CenterVC") as! CenterViewController
self.leftViewController = leftVC
self.rightViewController = CenterNC
self.centerView.delegate = self
// Do any additional setup after loading the view.
}
}
CenterViewController.swift
import UIKit
protocol test{
func showMenu()
func hideMenu()
}
class CenterViewController: UIViewController {
var delegate:test! = nil
#IBAction func pressed(sender: AnyObject) {
if (delegate != nil) {
delegate.showMenu()
}
else{
print("Error")
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Debug ContainerView.swift
Debug CenterViewController.swift

Usually you use whatever.delegate = self but I'm not quite sure what you want to do. (Also whatever.datasource = self). I dont know if this works for VCs.
As far as I know it is bad practice to have one UIViewController in the storyboard that contains two other VCs.
Rather you should either transition programmatically or with a storyboard segue.
self.presentViewController(LeftViewController(), animated: true, completion: nil)
self.dismissViewController(true, completion: nil)
View Controllers are automatically removed from memory (look up ARC if your curious) (as long as you don't have variables in the VC to be removed that are (or can be) accessed from another class that wasn't deinitialized - if that's confusing ignore it)
If you want a sliding animation or something like this, it's probably best to find something on GitHub to clone and import into your project. I've made an app with a tab bar that slides between views with some code I found online.
I've been droning but having two VCs in one VC is terrible for memory and in general bad practice. Utilize Custom Segues instead.

Related

How do you really hide and show a tab bar when tapping on part of your view? (no buttons but any location of the screen)

override func viewDidLoad() {
let tap = UITapGestureRecognizer(target: self, action: #selector(touchHandled))
view.addGestureRecognizer(tap)
}
#objc func touchHandled() {
tabBarController?.hideTabBarAnimated(hide: true)
}
extension UITabBarController {
func hideTabBarAnimated(hide:Bool) {
UIView.animate(withDuration: 2, animations: {
if hide {
self.tabBar.transform = CGAffineTransform(translationX: 0, y: 100)
} else {
self.tabBar.transform = CGAffineTransform(translationX: 0, y: -100)
}
})
}
}
I can only hide the tab bar but I can't make it show when you tap again. I tried to look for answers on stack overflow but the answers seems to only work if you're using a button or a storyboard.
Have a variable isTabBarHidden in class which stores if the tabBar has been animated to hide. (You could have used tabBar.isHidden, but that would complicate the logic a little bit when animate hiding and showing)
class ViewController {
var isTabBarHidden = false // set the default value as required
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(touchHandled))
view.addGestureRecognizer(tap)
}
#objc func touchHandled() {
guard let tabBarControllerFound = tabBarController else {
return
}
tabBarController?.hideTabBarAnimated(hide: !isTabBarHidden)
isTabBarHidden = !isTabBarHidden
}
}
Generalised solution with protocol which will work in all the screens
Create UIViewController named BaseViewController and make it base class of all of your view controllers
Now Define protocol
protocol ProtocolHideTabbar:class {
func hideTabbar ()
}
protocol ProtocolShowTabbar:class {
func showTabbar ()
}
extension ProtocolHideTabbar where Self : UIViewController {
func hideTabbar () {
self.tabBarController?.tabBar.isHidden = true
}
}
extension ProtocolShowTabbar where Self : UIViewController {
func showTabbar () {
self.tabBarController?.tabBar.isHidden = false
}
}
By default we want show tabbar in every view controller so
extension UIViewController : ProtocolShowTabbar {}
In your BaseView Controller
in view will appear method add following code to show hide based on protocol
if self is ProtocolHideTabbar {
( self as! ProtocolHideTabbar).hideTabbar()
} else if self is ProtocolShowTabbar{
( self as ProtocolShowTabbar).showTabbar()
}
How to use
Simply
class YourViewControllerWithTabBarHidden:BaseViewController,ProtocolHideTabbar {
}
Hope it is helpful
Tested 100% working
Please try below code for that in UITabBarController subclass
var isTabBarHidden:Bool = false
func setTabBarHidden(_ tabBarHidden: Bool, animated: Bool,completion:((Void) -> Void)? = nil) {
if tabBarHidden == isTabBarHidden {
self.view.setNeedsDisplay()
self.view.layoutIfNeeded()
//check tab bar is visible and view and window height is same then it should be 49 + window Heigth
if (tabBarHidden == true && UIScreen.main.bounds.height == self.view.frame.height) {
let offset = self.tabBar.frame.size.height
self.view.frame = CGRect(x:0, y:0, width:self.view.frame.width, height:self.view.frame.height + offset)
}
if let block = completion {
block()
}
return
}
let offset: CGFloat? = tabBarHidden ? self.tabBar.frame.size.height : -self.tabBar.frame.size.height
UIView.animate(withDuration: animated ? 0.250 : 0.0, delay: 0.1, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: [.curveEaseIn, .layoutSubviews], animations: {() -> Void in
self.tabBar.center = CGPoint(x: CGFloat(self.tabBar.center.x), y: CGFloat(self.tabBar.center.y + offset!))
//Check if View is already at bottom so we don't want to move view more up (it will show black screen on bottom ) Scnario : When present mail app
if (Int(offset!) <= 0 && UIScreen.main.bounds.height == self.view.frame.height) == false {
self.view.frame = CGRect(x:0, y:0, width:self.view.frame.width, height:self.view.frame.height + offset!)
}
self.view.setNeedsDisplay()
self.view.layoutIfNeeded()
}, completion: { _ in
if let block = completion {
block()
}
})
isTabBarHidden = tabBarHidden
}
Hope it is helpful

SubView(nib) wont remove after calling removeFromSuperView()

I have an overlay view to segregate content, I'm checking for authentication in viewWillAppear() and I have a Notification subscribed to my Auth method. If I authenticate before any of my other views appear the overlay does not show up, however it does on the first view and will not go away even after calling removeFromSuperView().
import UIKit
import FirebaseAuth
class ProtectedViewController: UIViewController, ForceSignInBannerDelegate,
SignUpViewControllerDelegate, LoginViewControllerDelegate{
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
NotificationCenter.default.addObserver(self, selector: #selector(checkAuthentication), name: .myNotification, object: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.checkAuthentication()
}
func checkAuthentication() {
let bannerViewController = ForceSignInBanner.instanceFromNib() as! ForceSignInBanner
bannerViewController.delegate = self
if (!AuthenticationService.sharedInstance.isAuthenticated()) {
self.setView(view: bannerViewController, hidden: false)
print("Need to login")
} else if(AuthenticationService.sharedInstance.isAuthenticated()) {
self.setView(view: bannerViewController, hidden: true)
}
}
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: { _ in
view.isHidden = hidden
if hidden {
view.removeFromSuperview()
} else {
self.view.addSubview(view)
}
}, completion: nil)
}
It's because you're trying to remove a new ForceSignInBanner each time. Ideally you should create it once and keep a reference to the ForceSignInBanner created (as an optional property of ProtectedViewController).
Then remove the ForceSignInBanner that you've stored in the property.
class ProtectedViewController: UIViewController, ForceSignInBannerDelegate {
// This lazily loads the view when the property is first used and sets the delegate.
// Ideally you wouldn't force-case the `as` but I've left it for simplicity here.
private lazy var forceSignInBannerView: ForceSignInBanner = {
let forceSignInBannerView = ForceSignInBanner.instanceFromNib() as! ForceSignInBanner
forceSignInBannerView.delegate = self
return forceSignInBannerView
}()
// ... your other code ... //
fun toggleForceSignInBannerViewVisibility(isVisible: Bool) {
if isVisible {
view.addSubview(forceSignInBannerView)
} else {
forceSignInBannerView.removeFromSuperview()
}
}
}

How can I block any interaction on MapView? [duplicate]

This question already has answers here:
How to disable user interaction on MKMapView?
(4 answers)
Closed 6 years ago.
I'm designing a Slide Navigation Panel due to that tutorial.
Everything works fine. Now I want to go further and work on some UX issues.
This is how my app look like now. But still I can manipulate MapView. My goal is to do two things:
1) Prevent all interaction with MapView, such as scaling and moving
2) Close navigation panel, while tapping on viewController with map.
The main file for controlling this two controlller is containerViewController. Here is the source code for it:
import UIKit
import QuartzCore
enum SlideOutState {
case BothCollapsed
case LeftPanelExpanded
}
class ContainerViewController: UIViewController {
var centerNavigationController: UINavigationController!
var centerViewController: ViewController!
var currentState: SlideOutState = .BothCollapsed {
didSet {
let shouldShowShadow = currentState != .BothCollapsed
showShadowForCenterViewController(shouldShowShadow)
}
}
var leftViewController: SidePanelViewController?
override func viewDidLoad() {
super.viewDidLoad()
centerViewController = UIStoryboard.centerViewController()
centerViewController.delegate = self
// wrap the centerViewController in a navigation controller, so we can push views to it
// and display bar button items in the navigation bar
centerNavigationController = UINavigationController(rootViewController: centerViewController)
view.addSubview(centerNavigationController.view)
addChildViewController(centerNavigationController)
centerNavigationController.didMoveToParentViewController(self)
}
}
let centerPanelExpandedOffset: CGFloat = 60
extension ContainerViewController: CenterViewControllerDelegate {
func toggleLeftPanel() {
let notAlreadyExpanded = (currentState != .LeftPanelExpanded)
if notAlreadyExpanded {
addLeftPanelViewController()
}
animateLeftPanel(shouldExpand: notAlreadyExpanded)
}
func addLeftPanelViewController() {
if (leftViewController == nil) {
leftViewController = UIStoryboard.leftViewController()
leftViewController!.categories = Category.allCats()
addChildSidePanelController(leftViewController!)
}
}
func addChildSidePanelController(sidePanelController: SidePanelViewController) {
view.insertSubview(sidePanelController.view, atIndex: 0)
addChildViewController(sidePanelController)
sidePanelController.didMoveToParentViewController(self)
}
func animateLeftPanel(shouldExpand shouldExpand: Bool) {
if (shouldExpand) {
currentState = .LeftPanelExpanded
animateCenterPanelXPosition(targetPosition: CGRectGetWidth(centerNavigationController.view.frame) - centerPanelExpandedOffset)
} else {
animateCenterPanelXPosition(targetPosition: 0) { finished in
self.currentState = .BothCollapsed
self.leftViewController!.view.removeFromSuperview()
self.leftViewController = nil;
}
}
}
func animateCenterPanelXPosition(targetPosition targetPosition: CGFloat, completion: ((Bool) -> Void)! = nil) {
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .CurveEaseInOut, animations: {
self.centerNavigationController.view.frame.origin.x = targetPosition
}, completion: completion)
}
func showShadowForCenterViewController(shouldShowShadow: Bool) {
if (shouldShowShadow) {
centerNavigationController.view.layer.shadowOpacity = 0.8
} else {
centerNavigationController.view.layer.shadowOpacity = 0.0
}
}
}
private extension UIStoryboard {
class func mainStoryboard() -> UIStoryboard { return UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()) }
class func leftViewController() -> SidePanelViewController? {
return mainStoryboard().instantiateViewControllerWithIdentifier("LeftViewController") as? SidePanelViewController
}
class func centerViewController() -> ViewController? {
return mainStoryboard().instantiateViewControllerWithIdentifier("CenterViewController") as? ViewController
}
}
My idea is to create variable that stands for active side panel and write a function, that will solve my issues:
I see something like that:
func blockCenterView() {
let AlreadyExpanded = (currentState = .LeftPanelExpanded)
if AlreadyExpanded {
//no idea what to write here
}
}
Am I right, or there exist other variants for solving that problem?
Try to set the following properties to false
mapView.zoomEnabled = false
mapView.scrollEnabled = false
mapView.userInteraction = false
Also check the Interface Builder for the user Interactions:
Add this code whereever you want to stop interaction with mapView
mapView.userInteractionEnabled = false
To enable it back,
mapView.userInteractionEnabled = true
Note : mapView is an instance of MKMapView
PS
SWRevealViewController
Source : Github
Step By Step Tutorial : More Flexible Slide View
This is what I was able to create using this awesome framework
App Link : AirMate on AppStore

UITabBarController height decreases everytime it's loaded

When I first load my application and log in. Everything is fine.
However when I log out, then log back in. The height of my view has been decreased. Here's a screenshot of the bug:
I havn't been able to find the cause of this. Making this quite a difficult question to ask help with as I can't specify the precise section of code causing the issue. But I'll try.
The problematic setup is like so:
I have a containerViewController, with 2 childViewControllers, a menu and a UITabBarController. The UITabBarController has 2 UIViewControllers.
To better explain it, here's a visual representation.
_______________________
App Start ->
NavigationController(rootViewController LandingPageVC)
LandingPageVC -> push -> SignInVC(this is where I login from)
SignInVC -> push -> ContainerViewController(this has my UITabBarController and my menu)
ContainerViewController (sets up my menuTabBarController and menu)
menuTabBarController (this tabBarController is used to switch out my content from the menu)
SidePanelViewController (this is my menu)
ContainerViewController -> push(signing out) -> LandingPageVC
_______________________
Here's how I push the containerViewController when a successful login is called.
let mainTableViewController = ContainerViewController()
mainTableViewController.navigationItem.setHidesBackButton(true, animated: false)
navigationController!.pushViewController(mainTableViewController, animated: true)
menuEnabled = true
here's the function called from the containerViewController I use to log out.
func signOut() {
// Set up the landing page as the main viewcontroller again.
let mainTableViewController = LandingPageVC()
mainTableViewController.navigationItem.setHidesBackButton(true, animated: false)
mainTableViewController.skipView = false
self.navigationController!.pushViewController(mainTableViewController, animated: true)
// Disable menu access
menuEnabled = false
}
by printing the height of ContainerViewController and menuTabBarController, I found that it is the UITabBarController's height that's decreasing and not the ContainerViewController.
Here's the code that has to do with the UITabBarController
import UIKit
import QuartzCore
let menuTabBarController = UITabBarController()
var menuButton = UIBarButtonItem()
var menuEnabled = false
class ContainerViewController: UIViewController, CenterViewControllerDelegate, SidePanelViewControllerDelegate, UIGestureRecognizerDelegate {
func needsSignOut(sender: SidePanelViewController) {
// toggling left panel
self.toggleLeftPanel()
// signing out
self.signOut()
}
var centerViewController: UITabBarController!
var leftViewController: SidePanelViewController?
let centerPanelExpandedOffset: CGFloat = 60
override func viewDidLoad() {
super.viewDidLoad()
menuTabBarController.tabBar.hidden = true
menuButton = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.Plain, target: self, action: "toggleLeftPanel")
if let font = UIFont(name: "FontAwesome", size: 20) {
menuButton.setTitleTextAttributes([NSFontAttributeName: font], forState: UIControlState.Normal)
}
self.navigationItem.leftBarButtonItem = menuButton
//let tabBarController = UITabBarController()
let suggestionsVC = SuggestionsViewController()
let testVC = detaiLSuggestion_VC()
let controllers = [suggestionsVC,testVC]
menuTabBarController.setViewControllers(controllers, animated: false)
centerViewController = menuTabBarController
view.addSubview(menuTabBarController.view)
addChildViewController(menuTabBarController)
//centerNavigationController.didMoveToParentViewController(self)
}
// MARK: CenterViewController delegate methods
func toggleLeftPanel() {
let notAlreadyExpanded = (currentState != .LeftPanelExpanded)
if notAlreadyExpanded {
addLeftPanelViewController()
}
animateLeftPanel(shouldExpand: notAlreadyExpanded)
}
func collapseSidePanels() {
switch (currentState) {
case .LeftPanelExpanded:
toggleLeftPanel()
default:
break
}
}
func addLeftPanelViewController() {
if (leftViewController == nil) {
leftViewController = SidePanelViewController()
leftViewController!.delegate = self
addChildSidePanelController(leftViewController!)
}
}
func addChildSidePanelController(sidePanelController: SidePanelViewController) {
view.insertSubview(sidePanelController.view, atIndex: 0)
addChildViewController(sidePanelController)
sidePanelController.didMoveToParentViewController(self)
}
func animateLeftPanel(#shouldExpand: Bool) {
if (shouldExpand) {
currentState = .LeftPanelExpanded
animateCenterPanelXPosition(targetPosition: CGRectGetWidth(centerViewController.view.frame) - centerPanelExpandedOffset)
} else {
animateCenterPanelXPosition(targetPosition: 0) { finished in
self.currentState = .BothCollapsed
self.leftViewController!.view.removeFromSuperview()
self.leftViewController = nil;
}
}
}
func animateCenterPanelXPosition(#targetPosition: CGFloat, completion: ((Bool) -> Void)! = nil) {
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .CurveEaseInOut, animations: {
self.centerViewController.view.frame.origin.x = targetPosition
}, completion: completion)
}
Any help deducing where this is coming from or how I can go about fixing it would be greatly appreciated! And again I apologize for the dumb of code. I'll update it further if I am able to rule out parts of it.
rdelmar found a solution for me in chat.
The problem was fixed by specifying the menuTabBarController.view.frame like so:
menuTabBarController.view.frame = self.view.frame

NSInvalidArgumentException reason: 'Storyboard doesn't contain a view controller with identifier 'CenterViewController''

Error: Failed to instantiate the default view controller for UIMainStoryboardFile 'Main' - perhaps the designated entry point is not set?
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Storyboard (<UIStoryboard: 0x7ff949770c30>) doesn't contain a view controller with identifier 'CenterViewController''
I dont' know what's wrong with my Main Storyboard.I was building slide out navigation panel of my own.
CenterViewController.swift
import UIKit
#objc
protocol CenterViewControllerDelegate {
optional func toggleLeftPanel()
optional func collapseSidePanels()
}
class CenterViewController: UIViewController, SideMenuPanelViewControllerDelegate {
//#IBOutlet weak private var testimageView: UIImageView!
#IBOutlet weak private var testLabel:UILabel!
var delegate: CenterViewControllerDelegate?
// MARK: Button actions
#IBAction func MenuTapped(sender: AnyObject) {
delegate?.toggleLeftPanel?()
}
func localSelected(local: LocalMenus) {
//imageView.image = animal.image
testLabel.text = local.title
delegate?.collapseSidePanels?()
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
ContainerViewController.swift
import UIKit
import QuartzCore
enum SideOutState {
case BothCollapsed
case LeftPanelExpanded
case RightPanelExpanded
}
class ContainerViewController: UIViewController, CenterViewControllerDelegate, UIGestureRecognizerDelegate{
var centerNavigationController: UINavigationController!
var centerViewController: CenterViewController!
var currentState: SideOutState = .BothCollapsed {
didSet {
let shouldShowShadow = currentState != .BothCollapsed
showShadowForCenterViewController(shouldShowShadow)
}
}
var leftMenuController: SideMenuPanelViewController?
let centerPanelExpandedOffset: CGFloat = 60
override func viewDidLoad() {
super.viewDidLoad()
centerViewController = UIStoryboard.centerViewController()
centerViewController.delegate = self
// wrap the centerViewController in a navigation controller, so we can push views to it
// and display bar button items in the navigation bar
centerNavigationController = UINavigationController(rootViewController: centerViewController)
view.addSubview(centerNavigationController.view)
addChildViewController(centerNavigationController)
centerNavigationController.didMoveToParentViewController(self)
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: "handlePanGesture:")
centerNavigationController.view.addGestureRecognizer(panGestureRecognizer)
}
// MARK: CenterViewController delegate methods
func toggleLeftPanel() {
let notAlreadyExpanded = (currentState != .LeftPanelExpanded)
if notAlreadyExpanded {
addLeftPanelViewController()
}
animateLeftPanel(shouldExpand: notAlreadyExpanded)
}
func collapseSidePanels() {
switch (currentState) {
case .LeftPanelExpanded:
toggleLeftPanel()
default:
break
}
}
func addLeftPanelViewController() {
if (leftMenuController == nil) {
leftMenuController = UIStoryboard.leftMenuController()
leftMenuController!.local = LocalMenus.allLocal()
addChildSidePanelController(leftMenuController!)
}
}
func addChildSidePanelController(sidePanelController:SideMenuPanelViewController) {
sidePanelController.delegate = centerViewController
view.insertSubview(sidePanelController.view, atIndex: 0)
addChildViewController(sidePanelController)
sidePanelController.didMoveToParentViewController(self)
}
func animateLeftPanel(#shouldExpand: Bool) {
if (shouldExpand) {
currentState = .LeftPanelExpanded
animateCenterPanelXPosition(targetPosition: CGRectGetWidth(centerNavigationController.view.frame) - centerPanelExpandedOffset)
} else {
animateCenterPanelXPosition(targetPosition: 0) { finished in
self.currentState = .BothCollapsed
self.leftMenuController!.view.removeFromSuperview()
self.leftMenuController = nil;
}
}
}
func animateCenterPanelXPosition(#targetPosition: CGFloat, completion: ((Bool) -> Void)! = nil) {
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .CurveEaseInOut, animations: {
self.centerNavigationController.view.frame.origin.x = targetPosition
}, completion: completion)
}
func showShadowForCenterViewController(shouldShowShadow: Bool) {
if (shouldShowShadow) {
centerNavigationController.view.layer.shadowOpacity = 0.8
} else {
centerNavigationController.view.layer.shadowOpacity = 0.0
}
}
// MARK: Gesture recognizer
func handlePanGesture(recognizer: UIPanGestureRecognizer) {
// we can determine whether the user is revealing the left or right
// panel by looking at the velocity of the gesture
let gestureIsDraggingFromLeftToRight = (recognizer.velocityInView(view).x > 0)
switch(recognizer.state) {
case .Began:
if (currentState == .BothCollapsed) {
// If the user starts panning, and neither panel is visible
// then show the correct panel based on the pan direction
if (gestureIsDraggingFromLeftToRight) {
addLeftPanelViewController()
}
showShadowForCenterViewController(true)
}
case .Changed:
// If the user is already panning, translate the center view controller's
// view by the amount that the user has panned
recognizer.view!.center.x = recognizer.view!.center.x + recognizer.translationInView(view).x
recognizer.setTranslation(CGPointZero, inView: view)
case .Ended:
// When the pan ends, check whether the left or right view controller is visible
if (leftMenuController != nil) {
// animate the side panel open or closed based on whether the view has moved more or less than halfway
let hasMovedGreaterThanHalfway = recognizer.view!.center.x > view.bounds.size.width
animateLeftPanel(shouldExpand: hasMovedGreaterThanHalfway)
}
default:
break
}
}
}
private extension UIStoryboard {
class func mainStoryboard() -> UIStoryboard {
return UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
}
class func leftMenuController() -> SideMenuPanelViewController? {
return mainStoryboard().instantiateViewControllerWithIdentifier("SideMenuPanelViewController") as? SideMenuPanelViewController
}
class func centerViewController() -> CenterViewController? {
return mainStoryboard().instantiateViewControllerWithIdentifier("CenterViewController") as? CenterViewController
}
}
Very simple.
In your main storyboard, you have no ViewController with a Storyboard ID "CenterViewController"
Look here:
https://stackoverflow.com/a/11604827/3324388
Short answer from Xcode 8.0 onwards,
Go to the Main.storyboard select the target ViewController, press Command+option+3 to display the attributes
Fill the StoryBoard ID input field
Check the Use Storyboard ID checkbox
I know this could be found on the duplicated referred answer but you need to read, try and error etc.

Resources