UINavigationBar 中的 UIBarButtonItems 无法点击
UIBarButtonItems in UINavigationBar are unclickable
我的 UIBarButtonItems
似乎对点击没有任何反应。
我有一个连接到 TableViewController 的平移手势识别器,但是我已经确定在启用 panGestureRecognizer.cancelsTouchesInView
到 false
后这不会阻止它。
现在,导航控制器嵌入到我为管理滑出视图控制器而创建的 ContainerViewController 中,包括如下:
import UIKit
class InstructorSlideOutContainerViewController: SlideOutContainerViewController {
var isFromLogin:Bool?
override func viewDidLoad() {
super.viewDidLoad()
setLeftViewController(identifier: "InstructorSettingsTableViewController")
setCenterViewController(identifier: "InstructorClassesTableViewController")
(centerViewController as! InstructorClassesTableViewController).delegate = self
(centerViewController as! InstructorClassesTableViewController).touchDelegate = self
(centerViewController as! InstructorClassesTableViewController).isFromLogin = isFromLogin
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)
}
class func getEntrySegueFromFBLogin() -> String {
return "FBLoginToInstructorContainerSegue"
}
class func getEntrySegueFromLogin() -> String {
return "LoginToInstructorContainerSegue"
}
class func getEntrySegueFromSignUp() -> String {
return "LoginToInstructorContainerSegue"
}
}
它是广义的 ContainerViewController 的子类:
enum SlideOutState {
case LeftPanelClosed
case LeftPanelExpanded
}
import UIKit
protocol SlideOutContainerViewControllerDelegate {
func toggleLeftPanel()
}
protocol InitializeViewControllers {
func setLeftViewController(identifier: String)
func setCenterViewController(identifier: String)
}
class SlideOutContainerViewController: UIViewController {
var centerNavigationController: UINavigationController!
var centerViewController: UIViewController?
var currentState: SlideOutState = .LeftPanelClosed
var leftViewController: UIViewController?
var centerViewControllerIdentifer = ""
let centerPanelExpandedOffset: CGFloat = 60
var mainStoryboard:UIStoryboard?
override func viewDidLoad() {
super.viewDidLoad()
mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
}
}
extension SlideOutContainerViewController: InitializeViewControllers {
func setLeftViewController(identifier: String) {
leftViewController = mainStoryboard?.instantiateViewController(withIdentifier: identifier)
}
func setCenterViewController(identifier: String) {
centerViewController = mainStoryboard?.instantiateViewController(withIdentifier: identifier)
}
}
extension SlideOutContainerViewController: SlideOutContainerViewControllerDelegate {
func toggleLeftPanel(){
let notAlreadyExpanded = (currentState != .LeftPanelExpanded)
if notAlreadyExpanded {
addChildSidePanelController(sidePanelController: leftViewController!)
}
animateLeftPanel(shouldExpand: notAlreadyExpanded)
}
func addChildSidePanelController(sidePanelController: UIViewController) {
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()
}
}
}
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 SlideOutContainerViewController {
func handlePanGesture(_ recognizer: UIPanGestureRecognizer) -> Void {
let gestureIsDraggingFromLeftToRight = recognizer.velocity(in: view).x > 0
switch recognizer.state {
case .began:
if currentState == .LeftPanelClosed {
if gestureIsDraggingFromLeftToRight {
addChildSidePanelController(sidePanelController: leftViewController!)
}
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
}
}
}
这是故事板的屏幕截图。
所以基本上一旦 Containerviewcontroller
加载,我就不能使用导航栏中的任何按钮。 TableViewController
中的触摸仍然被注册,似乎它只是 UINavigationBar
中的 UIBarButtonItems
。
我仔细检查了所有插座是否已连接,现在正在努力寻找其他解决方案...
提前致谢!!
EDIT:如果我删除嵌入式故事板 UINavigationController,我可以让按钮工作,但是我需要它,这样当从另一个 UINavigationController 转至 <Back
箭头未显示在 NavigationController 的顶部。
解决方案是使用模式转场转场到 viewcontroller,因为 containerviewcontroller
正在与 navigationcontroller
竞争并且需要声明它是自己的而不是简单地被推到导航堆栈。
我的 UIBarButtonItems
似乎对点击没有任何反应。
我有一个连接到 TableViewController 的平移手势识别器,但是我已经确定在启用 panGestureRecognizer.cancelsTouchesInView
到 false
后这不会阻止它。
现在,导航控制器嵌入到我为管理滑出视图控制器而创建的 ContainerViewController 中,包括如下:
import UIKit
class InstructorSlideOutContainerViewController: SlideOutContainerViewController {
var isFromLogin:Bool?
override func viewDidLoad() {
super.viewDidLoad()
setLeftViewController(identifier: "InstructorSettingsTableViewController")
setCenterViewController(identifier: "InstructorClassesTableViewController")
(centerViewController as! InstructorClassesTableViewController).delegate = self
(centerViewController as! InstructorClassesTableViewController).touchDelegate = self
(centerViewController as! InstructorClassesTableViewController).isFromLogin = isFromLogin
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)
}
class func getEntrySegueFromFBLogin() -> String {
return "FBLoginToInstructorContainerSegue"
}
class func getEntrySegueFromLogin() -> String {
return "LoginToInstructorContainerSegue"
}
class func getEntrySegueFromSignUp() -> String {
return "LoginToInstructorContainerSegue"
}
}
它是广义的 ContainerViewController 的子类:
enum SlideOutState {
case LeftPanelClosed
case LeftPanelExpanded
}
import UIKit
protocol SlideOutContainerViewControllerDelegate {
func toggleLeftPanel()
}
protocol InitializeViewControllers {
func setLeftViewController(identifier: String)
func setCenterViewController(identifier: String)
}
class SlideOutContainerViewController: UIViewController {
var centerNavigationController: UINavigationController!
var centerViewController: UIViewController?
var currentState: SlideOutState = .LeftPanelClosed
var leftViewController: UIViewController?
var centerViewControllerIdentifer = ""
let centerPanelExpandedOffset: CGFloat = 60
var mainStoryboard:UIStoryboard?
override func viewDidLoad() {
super.viewDidLoad()
mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
}
}
extension SlideOutContainerViewController: InitializeViewControllers {
func setLeftViewController(identifier: String) {
leftViewController = mainStoryboard?.instantiateViewController(withIdentifier: identifier)
}
func setCenterViewController(identifier: String) {
centerViewController = mainStoryboard?.instantiateViewController(withIdentifier: identifier)
}
}
extension SlideOutContainerViewController: SlideOutContainerViewControllerDelegate {
func toggleLeftPanel(){
let notAlreadyExpanded = (currentState != .LeftPanelExpanded)
if notAlreadyExpanded {
addChildSidePanelController(sidePanelController: leftViewController!)
}
animateLeftPanel(shouldExpand: notAlreadyExpanded)
}
func addChildSidePanelController(sidePanelController: UIViewController) {
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()
}
}
}
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 SlideOutContainerViewController {
func handlePanGesture(_ recognizer: UIPanGestureRecognizer) -> Void {
let gestureIsDraggingFromLeftToRight = recognizer.velocity(in: view).x > 0
switch recognizer.state {
case .began:
if currentState == .LeftPanelClosed {
if gestureIsDraggingFromLeftToRight {
addChildSidePanelController(sidePanelController: leftViewController!)
}
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
}
}
}
这是故事板的屏幕截图。
Containerviewcontroller
加载,我就不能使用导航栏中的任何按钮。 TableViewController
中的触摸仍然被注册,似乎它只是 UINavigationBar
中的 UIBarButtonItems
。
我仔细检查了所有插座是否已连接,现在正在努力寻找其他解决方案...
提前致谢!!
EDIT:如果我删除嵌入式故事板 UINavigationController,我可以让按钮工作,但是我需要它,这样当从另一个 UINavigationController 转至 <Back
箭头未显示在 NavigationController 的顶部。
解决方案是使用模式转场转场到 viewcontroller,因为 containerviewcontroller
正在与 navigationcontroller
竞争并且需要声明它是自己的而不是简单地被推到导航堆栈。