【问题标题】:Xcode 8 / Swift 3 / ios 10 navigation bar changes?Xcode 8 / Swift 3 / ios 10 导航栏变化?
【发布时间】:2017-03-15 13:42:51
【问题描述】:

我正在返回“旧”xcode 7 / swift 2 项目。

我所有的导航栏都发生了一些奇怪的事情。

我有这样的代码:

@IBOutlet weak var outletCatalogNav: UINavigationItem!

//...

outletCatalogNav.title = "my title";

//...

outletCatalogNav.leftbarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ownCatalogBackButton));

//...    

if (outletCatalogNav.leftbarButtonItem != nil) {
  outletCatalogNav.leftbarButtonItem.leftBarButtonItem!.title = " back"
}

然后以这样的代码结束,用于切换视图:

TmpOldViewController.present(TmpNewViewController!, animated: TmpAnimate, completion: nil):

信息:由于历史原因,当 iOS 应用代码从完全不同的开发平台、语言和环境转换而来时,我自己处理视图控制器更改。

无论如何,在过去,按钮只会放在标题的左侧。现在在 ios10 模拟器中,至少它呈现在下方(但仍然在左侧),这意味着我用于导航栏的原始高度不再足够(因为它被其他控件覆盖) - 在下面的屏幕截图中你可以看到这带有左下角蓝色文本的提示。

约束是:

Navigation Bar.top = Top Layout Guide.bottom
TableViewCatalog.top = Navigation Bar.bottom
Navigation Bar.leading = leadingMargin - 20
trailingMargin = Navigation Bar.trailing - 20

发生了什么变化?我无法找到导航栏中发生的任何更改的参考。作为参考,自从改用swift 3后,我现在只针对ios8+,所以我不需要ios7兼容的解决方案。

【问题讨论】:

  • 你用的是独立的导航栏,那么(意思是只有导航栏,没有导航控制器)?
  • @leanne 是的 - 我添加了更多代码和解释以防万一。
  • 另外几个问题:1)导航栏还有哪些其他限制? 2) 在实际设备上运行时它会做同样的事情吗?
  • @leanne Navigation Bar.top = Top Layout Guide.bottom 和 TableViewCatalog.top = Navigation Bar.bottom(今天晚些时候将在 iphone 6 上测试,在 ios8+ 要求之后不得不放弃我的测试 iphone 4 所以目前使用模拟器)
  • 尝试通过创建一个全新的UIBarButtonItem 来替换.title = "back"。我认为计算条形按钮项的框架的方式发生了一些变化。

标签: swift3 xcode8 ios10


【解决方案1】:

我不知道 iOS 10 关于独立导航栏有什么变化,所以我无法具体回答你的问题。不过,我可以告诉你两种可能的修复方法:

1) 为独立导航栏设置适当的约束和值:
确保约束设置如下:
- Navigation Bar.Top = 顶部布局 Guide.Bottom
- 导航栏.Leading = Superview.Leading
- Navigation Bar.Trailing = Superview.Trailing

然后,在栏的身份检查器中,添加具有以下值的用户定义属性:
- 关键路径:barPosition
- 类型:数字
- 值:3

这会安装独立的导航栏,就像它连接到导航控制器一样。

注意:该栏将出现在情节提要中,就好像它不是正确的高度一样。没关系!它会在您实际运行应用程序时进行适当调整。

更新:相同的解决方案,但不使用“用户定义的属性”:
- 确保按上述方式设置约束。
- 将故事板的导航栏作为@IBOutlet 连接到其视图控制器。
- 在视图控制器的类中,将 UINavigationBarDelegate 协议添加到类声明中。
- 在视图控制器的 viewDidLoad 方法中,将导航栏的委托设置为 self.
- 在视图控制器中,添加 bar 定位委托的 positionForBar 方法。返回代表 TopAttached 的 UIBarPosition。 (注:UINavigationBarDelegate 继承自 UIBarPositioningDelegate 这个方法。)

有关更多详细信息,请参阅Easily use a Navigation Bar without a corresponding Navigation Controller 以获取演示 GIF。

有关“用户定义属性”方法的更多详细信息,请参阅Even more easily use a Navigation Bar without a corresponding Navigation Controller!

2) 将视图嵌入到导航控制器中:
- 在情节提要中,删除“独立”导航栏。
- 确保选择了带有导航栏的视图。
- 从菜单中,选择编辑器/嵌入/导航控制器。

注意:您不需要编写任何代码或为导航控制器创建子类。它会自动适当地处理您的导航栏。


附带说明:我有一个在 iOS 7 中创建的应用程序,它也有一个独立的导航栏。在 Xcode 8/iOS 10 中,它遇到了同样的问题。

我使用了上面的第一种方法,它修复了导航栏的问题。但是,然后我在启动时出现了闪烁(可能与 iOS 10 中的栏动画有关)。

我使用的是启动图像。我突然想到,与导航栏动画相比,图像可能会关闭。所以,我切换到方法 2,将我的视图嵌入到导航控制器中。然后,我删除了我一直在使用的启动图像,并添加了一个新的启动屏幕 - 使用嵌入在导航控制器中的视图构建。一起解决了闪烁问题。

【讨论】:

  • 有什么特别的原因你没有设置:TableViewCatalog.top = Navigation Bar.bottom?我可以保留它吗?
  • 使用解决方案 #1:通过设置 barPosition 执行的操作 - 可以在运行时以某种方式完成吗?
  • 您的解决方案 #2 - 这是否意味着我必须删除或至少重写我自己的所有逻辑,以便我在整个应用程序中使用来控制要呈现的视图? (这是一个相当简单的基于堆栈的逻辑,但仍然 - 理论上我可能有一天更喜欢“支持”多个级别)
  • 是的,您可以保留您的TableViewCatalog.top = Navigation Bar.bottom。而且,是的,有一种方法可以在运行时执行解决方案 #1。请参阅此博客文章:Easily use a Navigation Bar without a corresponding Navigation Controller
  • 我已更新我的答案,包括基本说明和解决方案 #1 两个版本的链接。
【解决方案2】:

通过 viewDidLoad() 中的一些疯狂试验和错误,我找到了发生此错误的原因:

如果我创建一个标题为空的按钮,我会遇到问题,例如:

outletCatalogNav.leftbarButtonItem = UIBarButtonItem(title: "", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ownCatalogBackButton));

使用非空标题创建并且它可以工作:

outletCatalogNav.leftbarButtonItem = UIBarButtonItem(title: "test", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ownCatalogBackButton));

在这两种情况下,标题实际上也是稍后设置的 - 但重要的是在创建按钮时有一个非空标题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    相关资源
    最近更新 更多