在关注精彩的Ray Wenderlich tutorial之后,我在我的应用程序中成功创建了一个Slide Out Container视图。
我想将此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
}
}
}
我需要能够换出center
和leftViewController
属性。我创建了一个超类,然后在子类中设置center
和leftViewControllers
&#39; viewDidLoad
s(见下文),但是这不起作用,应用程序在UIStoryboard
类func(也显示在下面)mainStoryBoard
的扩展名中突破了
超类:
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)
}
}
这是堆栈跟踪:
与EXC_BAD_ACCESS
打破的行:
我知道它很多,而且很有可能解决任何问题,但StackOverflow经常有神奇的方法......
答案 0 :(得分:1)
您的问题是您的Storyboard协议的实现,您正在递归地调用方法leftViewController
和centerViewController
,要求在storyboard中实例化名称但是再次调用centerViewController
并且递归循环
我认为您需要将这些属性定义为类属性,或者在协议中返回静态字符串值的方法,以避免递归调用
希望这有助于你
答案 1 :(得分:0)
在mainStoryboard中,您可以尝试覆盖子类中的mainStoryboard方法,而不是返回名为“Main”的UIStoryboard,以便从子类ViewController返回10x2
吗?