2017-08-14 19 views
1

在精彩的Ray Wenderlich tutorial之后,我成功在我的应用程序中创建了“滑出容器”视图。模块化滑出容器ViewController

我想在我的应用程序将这一ContainerViewController在另一个地方,所以想模块化将此视为不能复制和粘贴代码到另一个ViewController,但是我很茫然至于如何去这样做。

下面是从教程中的代码:

import UIKit 
enum SlideOutState { 
    case LeftPanelClosed 
    case LeftPanelExpanded 
} 

class StudentContainerViewController: UIViewController { 

    var centerNavigationController: UINavigationController! 
    var centerViewController: SearchClassesTableViewController! // <--- Need to change this 
    var currentState: SlideOutState = .LeftPanelClosed 
    var leftViewController: StudentSettingsTableViewController? // <--- And this bad boy 
    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.didMove(toParentViewController: self) 

     let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) 
     centerNavigationController.view.addGestureRecognizer(panGestureRecognizer) 
    } 
} 

private extension UIStoryboard { 
    class func mainStoryboard() -> UIStoryboard { return UIStoryboard(name: "Main", bundle: Bundle.main) } 

    class func leftViewController() -> StudentSettingsTableViewController? { 
     return mainStoryboard().instantiateViewController(withIdentifier: "StudentSettingsTableViewController") as? StudentSettingsTableViewController 
    } 

    class func centerViewController() -> SearchClassesTableViewController? { 
     return mainStoryboard().instantiateViewController(withIdentifier: "SearchClassesTableViewController") as? SearchClassesTableViewController 
    } 
} 

extension StudentContainerViewController: CenterViewControllerDelegate { 
    func toggleLeftPanel(){ 
     let notAlreadyExpanded = (currentState != .LeftPanelExpanded) 
     if notAlreadyExpanded { 
      addLeftPanelViewController() 
     } 
     animateLeftPanel(shouldExpand: notAlreadyExpanded) 
    } 

    func addLeftPanelViewController(){ 
     if leftViewController == nil { 
      leftViewController = UIStoryboard.leftViewController() 
      addChildSidePanelController(sidePanelController: leftViewController!) 
     } 
    } 

    func addChildSidePanelController(sidePanelController: StudentSettingsTableViewController) { 
     view.insertSubview(sidePanelController.view, at: 0) 
     addChildViewController(sidePanelController) 
     sidePanelController.didMove(toParentViewController: self) 
    } 

    func animateLeftPanel(shouldExpand: Bool){ 
     if shouldExpand { 
      currentState = .LeftPanelExpanded 
      animateCenterPanelXPosition(targetPosition: centerNavigationController.view.frame.width - centerPanelExpandedOffset) 
     } else { 
      animateCenterPanelXPosition(targetPosition: 0) {finished in 
       self.currentState = .LeftPanelClosed 
       self.leftViewController?.view.removeFromSuperview() 
       self.leftViewController = nil 
      } 
     } 
    } 

    func animateCenterPanelXPosition(targetPosition: CGFloat, completion: ((Bool) -> Void)! = nil) { 
     UIView.animate(withDuration: 0.5, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, 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 

extension StudentContainerViewController { 
    func handlePanGesture(_ recognizer: UIPanGestureRecognizer) -> Void { 
     let gestureIsDraggingFromLeftToRight = recognizer.velocity(in: view).x > 0 

     switch recognizer.state { 
     case .began: 
      if currentState == .LeftPanelClosed { 
       if gestureIsDraggingFromLeftToRight { 
        addLeftPanelViewController() 
       } 
       showShadowForCenterViewController(shouldShowShadow: true) 
      } 
     case .changed: 
      if gestureIsDraggingFromLeftToRight || currentState == .LeftPanelExpanded { 
       recognizer.view!.center.x = recognizer.view!.center.x + recognizer.translation(in: view).x 
       recognizer.setTranslation(CGPoint.zero, in: view) 
      } 
     case .ended: 
      if leftViewController != nil { 
       let hasMovedMoreThanHalfway = recognizer.view!.center.x > view.bounds.size.width 
       animateLeftPanel(shouldExpand: hasMovedMoreThanHalfway) 
      } 
     default: 
      break 
     } 
    } 
} 

我需要能够换出centerleftViewController性能。我做了一个超类,然后设置在子类中viewDidLoad S(见下文)centerleftViewControllers,然而这并没有工作,并且应用在UIStoryboard扩展破门,在mainStoryBoard类FUNC(如下所示)

超类:

class SlideOutContainerViewController: UIViewController { 

    var centerNavigationController: UINavigationController! 
    var centerViewController: UIViewController? 
    var currentState: SlideOutState = .LeftPanelClosed 
    var leftViewController: UIViewController? 
    let centerPanelExpandedOffset: CGFloat = 60 


...same code as above... 
} 

和子类:

class StudentSlideOutContainerViewController: SlideOutContainerViewController { 

override func viewDidLoad() { 
    super.viewDidLoad() 
    centerViewController = SearchClassesTableViewController() 
    leftViewController = StudentSettingsTableViewController() 

     centerViewController = UIStoryboard.centerViewController() as! SearchClassesTableViewController 
//  centerViewController.delegate = self 

    centerNavigationController = UINavigationController(rootViewController: centerViewController!) 
    view.addSubview(centerNavigationController.view) 
    addChildViewController(centerNavigationController) 

    centerNavigationController.didMove(toParentViewController: self) 

    let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(_:))) 
    centerNavigationController.view.addGestureRecognizer(panGestureRecognizer) 

    } 
} 

这里的堆栈跟踪:

img1

而且符合EXC_BAD_ACCESS突破:

img2

我知道这是一个很多,一个长镜头解决的任何机会,但StackOverflow上往往具有神奇的方式....

+1

由于某种原因你的编码是递归调用'centerViewController'甲基这是什么导致你的崩溃,你可以发布你的类,你在实现这个故事板方法吗? –

回答

1

你的问题是你对你的故事板协议的实施,您呼叫的递归两种方法leftViewControllercenterViewController要求名称中的故事板实例,但再次调用centerViewController且有递归循环

我想你需要定义你的协议返回一个静态字符串值,这些属性类的属性或方法,以避免递归调用

希望这有助于你

+1

啊,是的,总是有助于有第二双眼睛,谢谢。 –

+1

我很高兴为您服务! @DaneJordan快乐的编码和最好的问候 –

0

在mainStoryboard中,您是否可以尝试覆盖子类中的mainStoryboard方法,而不是返回名为“Main”的UIStoryboard,以便从您的子类ViewController返回self.storyboard