简体   繁体   中英

Protocols problems in Swift

I'm implementing the RayWenderlich Slide out Navigation Panel: http://www.raywenderlich.com/78568/create-slide-out-navigation-panel-swift

And I want to open a new view ont Imageview tap like if I was clicking on the menu:

在此处输入图片说明

  • Link 2: NosOffres
  • Link 1: (index) Accueil (here is the Imageview)

Problem:

  • If I go in Link 2 from the Navigation/Menu, I can re-open the Navigation/Menu by slide or icon menu tap
  • If I go in Link 2 from the Image View, I can re-open the Navigation/Menu by slide but not with by icon menu tap

I tried many solutions and asked here for help but no way to have a response, now I tried an another thing, but I have a protocol problem:

I can't redeclare a protocol (in CenterViewController.swift), so I don't know how to do:

CenterViewController.swift:

@objc protocol CenterViewControllerDelegate {
    optional func toggleLeftPanel()
    optional func collapseSidePanels()
}

protocol CenterViewControllerDelegate {
    func itemSelected(item: AccueilItem)
}

class CenterViewController: UIViewController {

    var delegate: CenterViewControllerDelegate?
    var menus: Array<Menu>!
    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationController?.navigationBar.barTintColor = UIColor(red: 38.0/255.0, green: 51.0/255.0, blue: 85.0/255.0, alpha: 1.0)
        self.navigationController?.navigationBar.titleTextAttributes = [NSFontAttributeName: UIFont(name: "Gotham", size: 13)!, NSForegroundColorAttributeName : UIColor.whiteColor()]
        self.title = "ACCUEIL"
        // Do any additional setup after loading the view, typically from a nib.
    }

    @IBAction func menuTapped(sender: AnyObject) {
        delegate?.toggleLeftPanel?()
    }



    @IBAction func nosOffresTapped(sender: AnyObject) {
        print("lol")

        delegate?.itemSelected(AccueilItem(rawValue: "NosOffres")!)
    }

}


enum AccueilItem: String {
    case Accueil
    case NosOffres
    case DemandeGratuite
    case ContactezNous
    case Actualites
    case MentionsLegales

    func viewController() -> UIViewController {
        switch (self) {
        case Accueil: return UIStoryboard.centerViewController()!
        case NosOffres: return UIStoryboard.nosOffresViewController()!
        case DemandeGratuite: return {
            let vc = UIViewController();
            vc.view.backgroundColor = UIColor.orangeColor();
            return vc
            }()
        case ContactezNous: return UIStoryboard.nosOffresViewController()!
        case Actualites: return UIStoryboard.nosOffresViewController()!
        case MentionsLegales: return UIStoryboard.nosOffresViewController()!
        }
    }
}


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() -> CenterViewController? {
        return mainStoryboard().instantiateViewControllerWithIdentifier("CenterViewController") as? CenterViewController
    }

    class func nosOffresViewController() -> NosOffresViewController? {
        return mainStoryboard().instantiateViewControllerWithIdentifier("NosOffresViewController") as? NosOffresViewController
    }

}

NosOffresViewController.swift:

@objc
protocol NosOffresViewControllerDelegate {
    optional func toggleLeftPanel()
    optional func collapseSidePanels()
}

class NosOffresViewController: UIViewController {

    var delegate: NosOffresViewControllerDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.navigationController?.navigationBar.barTintColor = UIColor(red: 38.0/255.0, green: 51.0/255.0, blue: 85.0/255.0, alpha: 1.0)
        self.navigationController?.navigationBar.titleTextAttributes = [NSFontAttributeName: UIFont(name: "Gotham", size: 13)!, NSForegroundColorAttributeName : UIColor.whiteColor()]
        self.title = "NOS OFFRES"
        // Do any additional setup after loading the view, typically from a nib.
    }
}

ContainerViewController.swift:

    enum SlideOutState{
        case BothCollapsed
        case LeftPanelExpanded
    }

    class ContainerViewController: UIViewController, CenterViewControllerDelegate, SidePanelViewControllerDelegate, UIGestureRecognizerDelegate {

        var centerNavigationController: UINavigationController!
        var centerViewController: CenterViewController!

        var currentState: SlideOutState = .BothCollapsed

        var leftViewController: SidePanelViewController?

        let centerPanelExpandedOffset: CGFloat = 60

        override func viewDidLoad() {
            super.viewDidLoad()

            centerViewController = UIStoryboard.centerViewController()
            centerViewController.delegate = self

            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


    extension ContainerViewController {
        func itemSelected(item: MenuItem) {
            let vc = item.viewController()
            //create a new button
            let button: UIButton = UIButton(type: UIButtonType.Custom)
            //set image for button
            button.setImage(UIImage(named:"IconeMenu"), forState: UIControlState.Normal)
            //add function for button
            button.addTarget(self, action: "toggleLeftPanel", forControlEvents: UIControlEvents.TouchUpInside)
            //set frame
            button.frame = CGRectMake(0, 0,30, 30)

            let barButton = UIBarButtonItem(customView: button)
            //assign button to navigationbar
            vc.navigationItem.leftBarButtonItem = barButton
            self.centerNavigationController.viewControllers = [vc]
            self.collapseSidePannels()
        }


        func nosOffresSelected(item: AccueilItem) {
            let vc = item.viewController()
            //create a new button
            let button: UIButton = UIButton(type: UIButtonType.Custom)
            //set image for button
            button.setImage(UIImage(named:"IconeMenu"), forState: UIControlState.Normal)
            //add function for button
            button.addTarget(self, action: "toggleLeftPanel", forControlEvents: UIControlEvents.TouchUpInside)
            //set frame
            button.frame = CGRectMake(0, 0,30, 30)

            let barButton = UIBarButtonItem(customView: button)
            //assign button to navigationbar
            vc.navigationItem.leftBarButtonItem = barButton
            self.centerNavigationController.viewControllers = [vc]
            self.collapseSidePannels()
        }
    }

    extension ContainerViewController {

        func toggleLeftPanel() {
            let notAlreadyExpanded = (currentState != .LeftPanelExpanded)

            if notAlreadyExpanded {
                addLeftPanelViewController()
            }

            animateLeftPanel(shouldExpand: notAlreadyExpanded)
        }

        func collapseSidePannels() {
            switch (currentState) {
            case .LeftPanelExpanded:
                toggleLeftPanel()
            default:
                break
            }
        }

        func addLeftPanelViewController() {
            if (leftViewController == nil) {
                leftViewController = UIStoryboard.leftViewController()
                leftViewController!.menus = Menu.allMenu()

                addChildSidePanelController(leftViewController!)
            }
        }

        func addChildSidePanelController(sidePanelController: SidePanelViewController) {

            sidePanelController.delegate = self
            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)
        }

    }


    extension ContainerViewController {
        // MARK: Gesture recognizer

        func handlePanGesture(recognizer: UIPanGestureRecognizer) {
            let gestureIsDraggingFromLeftToRight = (recognizer.velocityInView(view).x > 0)

            switch(recognizer.state) {
            case .Began:
                if (currentState == .BothCollapsed) {
                    if (gestureIsDraggingFromLeftToRight) {
                        addLeftPanelViewController()
                    }
                }
            case .Changed:
                if (((recognizer.view!.center.x + recognizer.translationInView(view).x) > view.center.x || gestureIsDraggingFromLeftToRight) && (recognizer.view!.center.x >= view.center.x && recognizer.velocityInView(view).x > 0 || recognizer.view!.center.x > view.center.x && recognizer.velocityInView(view).x < 0) && recognizer.view!.center.x + recognizer.translationInView(view).x > view.center.x) {
                    recognizer.view!.center.x = recognizer.view!.center.x + recognizer.translationInView(view).x
                    recognizer.setTranslation(CGPointZero, inView: view)
                }
            case .Ended:
                if (leftViewController != 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 leftViewController() -> SidePanelViewController? {
            return mainStoryboard().instantiateViewControllerWithIdentifier("LeftViewController") as? SidePanelViewController
        }

        class func centerViewController() -> CenterViewController? {
            return mainStoryboard().instantiateViewControllerWithIdentifier("CenterViewController") as? CenterViewController
        }

        class func nosOffresViewController() -> NosOffresViewController? {
            return mainStoryboard().instantiateViewControllerWithIdentifier("NosOffresViewController") as? NosOffresViewController
        }

    }

SidePanelViewController.swift:

protocol SidePanelViewControllerDelegate {
    func itemSelected(item: MenuItem)
}

class SidePanelViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    var delegate: SidePanelViewControllerDelegate?

    var menus: Array<Menu>!

    struct TableView {
        struct CellIdentifiers {
            static let MenuCell = "MenuCell"
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let tblView = UIView(frame: CGRectZero)
        tableView.tableFooterView = tblView
        tableView.tableFooterView!.hidden = true
        tableView.backgroundColor = UIColor(red: 71.0/255.0, green: 88.0/255.0, blue: 130.0/255.0, alpha: 1.0)
        tableView.reloadData()
    }
}

extension SidePanelViewController: UITableViewDataSource {
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 6
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier(TableView.CellIdentifiers.MenuCell, forIndexPath: indexPath) as! MenuCell
        cell.configureForMenu(menus[indexPath.row])
        return cell
    }
}

// Mark: Table View Delegate

extension SidePanelViewController: UITableViewDelegate {
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        _ = menus[indexPath.row]
        delegate?.itemSelected(MenuItem(rawValue: indexPath.row)!)
    }
}


enum MenuItem: Int {
    case Accueil
    case NosOffres
    case DemandeGratuite
    case ContactezNous
    case Actualites
    case MentionsLegales

    func viewController() -> UIViewController {
        switch (self) {
        case Accueil: return UIStoryboard.centerViewController()!
        case NosOffres: return UIStoryboard.nosOffresViewController()!
        case DemandeGratuite: return {
            let vc = UIViewController();
            vc.view.backgroundColor = UIColor.orangeColor();
            return vc
            }()
        case ContactezNous: return UIStoryboard.nosOffresViewController()!
        case Actualites: return UIStoryboard.nosOffresViewController()!
        case MentionsLegales: return UIStoryboard.nosOffresViewController()!
        }
    }
}


class MenuCell: UITableViewCell {

    @IBOutlet weak var label: UILabel!

    func configureForMenu(menu: Menu) {
        label.text = menu.title
    }

}


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() -> CenterViewController? {
        return mainStoryboard().instantiateViewControllerWithIdentifier("CenterViewController") as? CenterViewController
    }

    class func nosOffresViewController() -> NosOffresViewController? {
        return mainStoryboard().instantiateViewControllerWithIdentifier("NosOffresViewController") as? NosOffresViewController
    }

}

I really don't know how to do here I tried to do the same thing of SidePanelViewController to CenterViewController, but I don't know if they're an another solution, help me please.

Your problem resides in when you use the menu to show a new UIViewController you are manipulating the navigationItem in your ContainerViewController in this way:

 func itemSelected(item: MenuItem) {
    let vc = item.viewController()
    //create a new button
    let button: UIButton = UIButton(type: UIButtonType.Custom)
    //set image for button
    button.setImage(UIImage(named:"IconeMenu"), forState: UIControlState.Normal)
    //add function for button
    button.addTarget(self, action: "toggleLeftPanel", forControlEvents: UIControlEvents.TouchUpInside)
    //set frame
    button.frame = CGRectMake(0, 0,30, 30)

    let barButton = UIBarButtonItem(customView: button)
    //assign button to navigationbar
    vc.navigationItem.leftBarButtonItem = barButton
    self.centerNavigationController.viewControllers = [vc]
    self.collapseSidePannels()
}

And for the above code the UINavigationController remains the same when you open the NosOffresViewController .

One way to solve your problem is add a new method in your CenterViewControllerDelegate and call it before push the new UIViewController and pass the reference to it:

@objc protocol CenterViewControllerDelegate {
   optional func toggleLeftPanel()
   optional func collapseSidePanels()
   optional func pushViewControllerInStack(viewController: UIViewController)
}

Like the following way:

@IBAction func nosOffresTapped(sender: AnyObject) {
    self.navigationController?.pushViewController(UIStoryboard.nosOffresViewController()!, animated: false)
    self.delegate?.pushViewControllerInStack!(UIStoryboard.nosOffresViewController()!)
}

And then in your ContainerViewController implements the method like in the following way:

func pushViewControllerInStack(viewController: UIViewController) {

    let vc = viewController
    //create a new button
    let button: UIButton = UIButton(type: UIButtonType.Custom)
    //set image for button
    button.setImage(UIImage(named:"IconeMenu"), forState: UIControlState.Normal)
    //add function for button
    button.addTarget(self, action: "toggleLeftPanel", forControlEvents: UIControlEvents.TouchUpInside)
    //set frame
    button.frame = CGRectMake(0, 0,30, 30)

    let barButton = UIBarButtonItem(customView: button)
    //assign button to navigationbar
    vc.navigationItem.leftBarButtonItem = barButton
    self.centerNavigationController.viewControllers = [vc]
    self.collapseSidePannels()
}

And this should work to present any new UIViewController from the CenterViewController .

I hope this help you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM