Swift中的协议问题

时间:2015-10-08 11:54:53

标签: ios swift menu navigation protocols

我正在实施RayWenderlich幻灯片导航面板:http://www.raywenderlich.com/78568/create-slide-out-navigation-panel-swift

我想在Imageview上打开一个新视图,就像点击菜单一样:

enter image description here

  • Link 2:NosOffres
  • 链接1 :(索引)Accueil(这是Imageview)

问题:

  • 如果我从导航/菜单进入链接2,我可以通过幻灯片或图标菜单点击重新打开导航/菜单
  • 如果我从图像视图进入链接2,我可以通过幻灯片重新打开导航/菜单,但不能通过图标菜单点击

我尝试了很多解决方案,并在这里寻求帮助,但没有办法得到回应,现在我尝试了另一件事,但我有一个协议问题:

我无法重新声明协议(在CenterViewController.swift中),因此我不知道该怎么做:

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
    }

}

我真的不知道该怎么做我尝试将SidePanelViewController用于CenterViewController,但我不知道他们是否是另一个解决方案,请帮助我。< / p>

1 个答案:

答案 0 :(得分:0)

当您使用菜单显示新UIViewController以这种方式操纵navigationItem中的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()
}

对于上述代码,当您打开UINavigationControllerNosOffresViewController保持不变。

解决问题的一种方法是在CenterViewControllerDelegate中添加新方法并在推送新UIViewController之前调用它并将引用传递给它:

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

喜欢以下方式:

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

然后在ContainerViewController中实现方法,如下所示:

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()
}

这应该可以显示UIViewController中的任何新CenterViewController

我希望这对你有所帮助。