我正在尝试覆盖导航控制器中后退按钮的默认操作 . 我已经在自定义按钮上提供了一个目标操作 . 奇怪的是,当通过backbutton属性分配它时,它不会注意它们,它只是弹出当前视图并返回到根:
UIBarButtonItem *backButton = [[UIBarButtonItem alloc]
initWithTitle: @"Servers"
style:UIBarButtonItemStylePlain
target:self
action:@selector(home)];
self.navigationItem.backBarButtonItem = backButton;
一旦我通过 navigationItem
上的 leftBarButtonItem
设置它就会调用我的动作,但是按钮看起来像一个普通的圆形而不是向后箭头:
self.navigationItem.leftBarButtonItem = backButton;
在返回根视图之前,如何让它调用我的自定义操作?有没有办法覆盖默认的后退操作,还是有一个方法在离开视图时总是被调用( viewDidUnload
不这样做)?
28 回答
使用
isMovingFromParentViewController
尝试将其放入要检测印刷机的视图控制器中:
我已经实现了UIViewController-BackButtonHandler扩展 . 它不需要子类化任何东西,只需将它放入您的项目并覆盖
UIViewController
类中的navigationShouldPopOnBackButton
方法:Download sample app .
与Amagrammer说的不同,这是可能的 . 你必须继承你的
navigationController
. 我解释了所有here(包括示例代码) .Swift版本:
(https://stackoverflow.com/a/19132881/826435)
在视图控制器中,您只需遵循协议并执行您需要的任何操作:
然后创建一个类,比如
NavigationController+BackButton
,只需复制粘贴下面的代码:不可能直接做 . 有几种选择:
创建您自己的自定义
UIBarButtonItem
,如果测试通过,则会自动点击并弹出使用
UITextField
委托方法验证表单字段内容,例如-textFieldShouldReturn:,在键盘上按下Return
或Done
按钮后调用该方法第一个选项的缺点是无法从自定义栏按钮访问后退按钮的左指箭头样式 . 因此,您必须使用图像或使用常规样式按钮 .
第二个选项很好,因为您在委托方法中返回了文本字段,因此您可以将验证逻辑定位到发送给委托回调方法的特定文本字段 .
由于某些线程原因,@ HansPinckaers提到的解决方案不适合我,但我找到了一种更简单的方法来触摸后退按钮,我想把它固定在这里,以防这可以避免数小时的欺骗其他人 . 诀窍很简单:只需将透明UIButton作为子视图添加到UINavigationBar中,并为他设置选择器,就像它是真正的按钮一样!这是使用Monotouch和C#的示例,但是对objective-c的转换不应该太难找到 .
有趣的事实:出于测试目的并为我的假按钮找到好的尺寸,我将其背景颜色设置为蓝色......并且它显示了 behind 后退按钮!无论如何,它仍然捕获任何触摸目标原始按钮 .
此技术允许您更改“后退”按钮的文本,而不会影响任何视图控制器的 Headers 或在动画期间看到后退按钮文本更改 .
将其添加到 calling 视图控制器中的init方法:
Easiest way
您可以使用UINavigationController的委托方法 . 按下VC的后退按钮时会调用方法
willShowViewController
. 按下btn后按下你想要的任何内容找到了一个保留后退按钮样式的解决方案 . 将以下方法添加到视图控制器 .
现在根据需要提供以下方法中的功能:
它只是用透明按钮覆盖后退按钮;)
我不相信这是可能的,很容易 . 我相信解决这个问题的唯一方法就是让你自己的后退按钮箭头图像放在那里 . 起初我很沮丧,但我明白为什么,为了保持一致,它被排除在外 .
您可以通过创建常规按钮并隐藏默认后退按钮来关闭(不使用箭头):
通过继承
UINavigationBar
的委托方法并覆盖ShouldPopItem
方法,有一种更简单的方法 .这是我的Swift解决方案 . 在UIViewController的子类中,重写navigationShouldPopOnBackButton方法 .
onegray的解决方案并不安全 . 根据Apple的官方文件,https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html,我们应该避免这样做 .
“如果在类别中声明的方法的名称与原始类中的方法相同,或者在同一个类(或甚至是超类)中的另一个类别中的方法相同,则对于使用哪个方法实现,行为未定义如果你在自己的类中使用类别,那么这不太可能成为问题,但在使用类别向标准Cocoa或Cocoa Touch类添加方法时可能会出现问题 . “
使用Swift:
这是Swift 3 @oneway 的答案,用于捕获导航栏后退按钮事件,然后才会被触发 . 由于
UINavigationBarDelegate
不能用于UIViewController
,因此需要创建一个在调用navigationBar
shouldPop
时触发的委托 .然后,在视图控制器中添加委托功能:
我意识到我们经常想为用户添加一个警报控制器来决定他们是否想回去 . 如果是这样,您可以始终在
navigationShouldPopOnBackButton()
函数中return false
并通过执行以下操作关闭视图控制器:通过使用当前保留为“nil”的目标和操作变量,您应该能够连接保存对话框,以便在“选择”按钮时调用它们 . 注意,这可能会在奇怪的时刻触发 .
我主要同意Amagrammer,但我不认为用按钮定制按钮会很难 . 我只需要重命名后退按钮,拍摄一个屏幕截图,然后按照所需的按钮尺寸,将其作为按钮顶部的图像 .
您可以尝试访问NavigationBars右键按钮项并设置其选择器属性...这是一个参考UIBarButtonItem reference,另一件事,如果这个最干净的工作将def工作,将导航栏的右按钮项设置为您创建的自定义UIBarButtonItem并设置其选择器...希望这有帮助
对于需要这样的用户输入的表单,我建议将其调用为“模态”而不是导航堆栈的一部分 . 这样他们就必须在表单上处理业务,然后您可以使用自定义按钮对其进行验证并将其解除 . 您甚至可以设计一个与应用程序其余部分看起来相同的导航栏,但可以为您提供更多控制 .
至少在Xcode 5中,有一个简单而且非常好(不完美)的解决方案 . 在IB中,将“按钮项”拖出“实用工具”窗格,然后将其放在导航栏左侧的“后退”按钮所在的位置 . 将标签设置为“返回” . 你将有一个功能按钮,你可以绑定到你的IBAction并关闭你的viewController . 我正在做一些工作,然后触发一个放松的segue,它完美地工作 .
不理想的是,这个按钮没有得到<箭头,也没有结转以前的VC Headers ,但我认为这可以管理 . 为了我的目的,我将新的后退按钮设置为“完成”按钮,因此它的目的很明确 .
您最终还会在IB导航器中使用两个Back按钮,但为了清晰起见,它很容易标记 .
迅速
这种方法适用于我(但“后退”按钮不会有“<”符号):
Swift 4 iOS 11.3版本:
这是基于来自https://stackoverflow.com/a/34343418/4316579的kgaidis的答案
我不确定扩展何时停止工作,但在撰写本文时(Swift 4),似乎扩展将不再执行,除非您声明UINavigationBarDelegate符合性如下所述 .
希望这有助于那些想知道为什么他们的扩展不再有效的人 .
@William的答案是正确的,但是,如果用户启动向后滑动手势,则会调用
viewWillDisappear
方法,甚至self
也不会在导航堆栈中(即self.navigationController.viewControllers
将不包含self
),即使滑动未完成且视图控制器实际上没有弹出 . 因此,解决方案是:viewDidAppear
中的滑动到后退手势,并且只允许使用后退按钮,方法是:viewDidDisappear
,如下所示:要拦截后退按钮,只需用透明的UIControl覆盖它并拦截触摸 .
到目前为止我找到的解决方案不是很好,但它对我有用 . 拿这个answer,我也检查一下我是否以编程方式弹出:
在以编程方式弹出之前,必须将该属性添加到控制器并将其设置为YES:
找到了新方法:
Objective-C
斯威夫特
Swift version of @onegray's answer
现在在任何控制器中,只需符合
RequestsNavigationPopVerification
,默认情况下会采用此行为 .