UIBarButtonItem 工作但在 Xcode 11 和 Xcode 12 中不可见

Posted

技术标签:

【中文标题】UIBarButtonItem 工作但在 Xcode 11 和 Xcode 12 中不可见【英文标题】:UIBarButtonItem working but not visible with Xcode11 and Xcode12 【发布时间】:2020-10-13 08:53:54 【问题描述】:

将我们的应用程序从 Xcode10 迁移到 Xcode12 后,我们的 UIBarButtonItems 出现了问题。其中一些不可见,但仍在工作。

我们能够更具体地定位以下目标:

ios12 上的 Xcode10.3:没问题 Xcode10.3 在 iOS13 上通过发布:没有问题 Xcode10.3 在 iOS14 上通过发布:没有问题 iOS12 上的 Xcode11.7:没问题 iOS13 上的 Xcode11.7:存在问题 iOS12 上的 Xcode12.0.1:没问题 iOS13 上的 Xcode12.0.1:存在问题 iOS14 上的 Xcode12.0.1:存在问题 问题出现在 Debug 和 Release 中 当我们从 Xcode 运行应用程序时没有出现问题 仅当我们退出应用并直接从设备再次启动时才会出现问题 仅当 UIBarButtonItem 为带有图标的系统项时才会出现问题,例如:刷新、添加、... UIBarButtonItem 是带有文本的系统项时不会出现问题,例如:编辑、关闭、... 当 UIBarButtonItem 使用来自资产的图像进行自定义时,问题不会出现 如果我以编程方式执行 UIBarButtonItem 系统,也会出现问题

查看“层次结构视图”时,项目及其图标在那里,但未显示在设备上。 我们看不出显示或不显示项目的任何差异,这有助于理解问题。

截图如下:

    故事板 从图标启动后在 iPad 上出现问题 查看问题的层次结构

更多截图(比较)可在此处获得:https://imgur.com/a/7Dcyvir

是否有人在 Xcode11 或 Xcode12 上看到过类似的行为? 知道我们可以尝试什么,或者它是否是需要报告修复的 Xcode 问题?

提前感谢您的帮助!

【问题讨论】:

您可以检查在所有部署目标版本中的普通 UIView 中作为普通 UIImage 实现时系统符号图像“arrow.clock”是否可用。当直接在设备上启动时图标未出现时,您还可以检查您的 initWithCoder 函数是否正确启动。一些符号已被弃用并且根本不会出现,因为它们不存在,所以像服装图像资产这样的后备机制可以解决它。 您好@OlSen,我已经尝试使用带有系统映像arrow.clockwise 和此映像works fine 的UIImageView,即使我重新启动应用程序也是如此。 UIViewController 这里不是自定义的,但我尝试了一个简单的,只是为了用日志验证流程。无论我使用 Xcode 还是图标启动都是正确的:initWithCoder > viewDidLoad > viewWillAppear > viewWillLayoutSubviews > viewDidLayoutSubviews > viewDidAppear. 然后我会尝试交换图标排序并观察最右边的图标是否消失。这样你就知道这显然是一个布局问题。然后可能是因为在加载 ViewController 的 View 时帧宽度是未知的。您可以在所有布局方法中通过多个NSLog(@"width = %f", frame.width) 观看此内容.. 您会发现一些方法在调用时没有宽度.. 已经试过了,不管在什么位置,带系统图标的项目都不出现... :( 【参考方案1】:

我们无法从头开始在另一个应用程序中重现。 因此,我们添加以相反的方式进行:剥离我们当前的应用程序,直到问题不再存在。 第一步是只拆掉一个 AppDelegate 和一段简单的代码,但问题仍然存在。 我们从 cocoapods 中删除了所有依赖项,但问题仍然存在。 我们最终删除了一个直接添加到项目中的框架,这是罪魁祸首!

上述框架是BiometricSDK(来自IDEMIA)。我们将向他们发送一封邮件,以了解他们是否知道此问题,以及他们是否已修复/将在较新的版本中修复它。它不是开源的,所以我不知道具体问题是什么,我唯一的猜测是他们以某种方式改变了 UIBarButtonItems 的外观(但我不确定他们的代码是如何调用的,因为我们已经删除了对它的任何引用,而剥离应用程序)。

【讨论】:

【参考方案2】:

系统字体符号自引入以来已更改,因此可以将它们称为 SF Symbols 1 和 SF Symbols 2,其中 SF Symbols 1 是 SF Symbols 2(支持多色符号)的一部分,其中一些也已更改详细。

一些符号(实际上很多)甚至在 iOS 13 之前就已经可用,但通常文档说...

SF 符号适用于 iOS 13 及更高版本、macOS 11 及更高版本、watchOS 6 及更高版本以及 tvOS 13 及更高版本。

因此,您尝试使用的特定符号 arrow.clockwise 是 SF Symbol 1 Collection 的一部分,并且是在 iOS 13 之前作为 Refresh Symbol 可用的符号之一。但是,当它们作为 SF Symbols 重新引入时,您会在这里遇到麻烦。在 iOS 13 以下的目标中,它们(一些)显示为 UIKit 控件的一部分,而在 iOS 12 之上,它们是系统字体符号,它们尊重 UI 的多个参数,如 darkMode、lightMode、anyMode、FontWeight、本地化等。

来自 Apple 文档..Creating Custom Symbols

如果您需要 SF Symbols 未提供的符号,您可以创建自己的符号。 SF Symbols 应用程序可让您以可重复使用的基于矢量的文件格式将符号导出为模板

还有

当您将 SF Symbols 2 中引入的符号导出为 SVG 模板 并将其与您的应用捆绑在一起时,您可以在面向 iOS 13、Mac Catalyst 13、tvOS 13 或watchOS 6,但没有 SF Symbol 2 的优势,例如多色支持和自动本地化。

提到的用于导出和验证 SVG 格式 SF 符号的 SF Symbols 工具可以在 here 找到。 了解 SF Symbols 1.1 应用程序如何 需要 macOS 10.14.4 或更高版本的样子。

箭头.顺时针符号没有标记(i),它会告诉您版权和其他您必须尊重的信息。

导出的 SVG 文件包含所有加权符号和布局指南,以保持这种 SF 符号功能,并将帮助您使用它开发图形。格式解释here

除非您的目标是 OSX 10.15 或 iOS 13,否则此 SVG 文件无法按原样拖放到您的应用资产中。如果您尝试在上述版本以下执行此操作,编译器会警告您。但您可以在 Sketch 或类似工具中打开它以编辑 SVG 数据并生成图形作为解决方法。我建议这样做,然后将此图形加载到您的 UI 元素中。

iOS 13 开始系统字体符号的使用及加载方法说明here

正如您在代码中以编程方式设置您的 UIBarButtonItem 一样,它也可以这样编写..

UIBarButtonItem *barBtn = nil;
if (@available(iOS 13.0, *)) 
    UITraitCollection *trait = [UITraitCollection currentTraitCollection];
    barBtn = [[UIBarButtonItem alloc] initWithImage:[UIImage systemImageNamed:@"arrow.clockwise" compatibleWithTraitCollection:trait] style:UIBarButtonItemStylePlain target:self action:@selector(refreshMethodHere)];
 else 
    barBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshMethodHere)];

【讨论】:

如果您以编程方式设置 UIBarButtonItem 的内容,请提供您的代码,因为很确定它可以通过针对 iOS 13 的两行代码来解决。 我在我们的项目/目标上的最低目标是 iOS12。可悲的是,我不只是在寻找一种解决方法。我知道如果我使用资产中的自定义图像,它可以正常工作。但这不是手动替换 Interface Builder 中的每个 System Item/Icon 的解决方案,有时也不是代码 [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshMethodHere)]; 中的每个 System Item/Icon 的解决方案。特别是它不仅仅是“刷新”,还有“添加”、“垃圾箱”等图标。 TSI 现已在 Apple Developer 开放,如有发现将发布。 更新了我的答案,因此您至少有一个取决于您的目标版本的解决方法。真正令人讨厌的是 UIBarButtonSystemItems 没有被标记为弃用,而它们的符号现在是对 UITraitCollection 作出反应的 SF 符号【参考方案3】:

当您将UIBarButtonItem 的标题文本属性foregroundColor 设置为UIColor.clear 时,可能会出现此问题。

你可以直接这样做,例如:

navigationItem.rightBarButtonItem?.setTitleTextAttributes([.foregroundColor: UIColor.clear], for: .normal)

或者通过修改UIBarButtonItem的外观,例如:

UIBarButtonItem.appearance().setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.clear], for: .normal)

检查你的代码,也许你在某个地方有这样的设置。

【讨论】:

以上是关于UIBarButtonItem 工作但在 Xcode 11 和 Xcode 12 中不可见的主要内容,如果未能解决你的问题,请参考以下文章

为啥 UIBarButtonItem 默认是禁用的?

iOS 11 uiBarButtonitem 尺寸缩小

存储在 plist 中的数据在模拟器中有效,但在设备中无效

UIBarButtonItem 在 ios6 中看起来很糟糕

UIBarButtonItem tintColor 停止工作

带有 customView 的 UIBarButtonItem 在 iOS4.1 中消失了