Xamarin.iOS 9 - 故障排除

本文提供了一些有关在 Xamarin.iOS 应用中使用 iOS 9 的故障排除提示。

iOS 8 模拟器在哪里?

如果已安装 Xcode 7(或更高版本),默认情况下,它会自动将所有 iOS 8 模拟器替换为 iOS 9 模拟器。 如果仍需要在 iOS 8 上进行测试,可启动 Xcode,然后下载并安装 iOS 8 模拟器。

在 Xcode 中,选择“Xcode”菜单,然后选择“首选项...”>“下载”:

iOS 8 模拟器下载

选择“立即检查并安装”按钮,重新安装 iOS 8 模拟器。

具有向左/向右特性错误的布局约束

在 iOS 8(及更低版本中),Storyboard 中的 UI 元素可在同一布局中使用向右特性和向左特性(NSLayoutAttributeRightNSLayoutAttributeLeft)以及前导特性和尾随特性(NSLayoutAttributeLeadingNSLayoutAttributeTrailing)的组合。

如果同一 Storyboard 在 iOS 9 中运行,则会导致出现以下形式的异常:

由于未捕获的异常 "NSInvalidArgumentException" 而终止应用,原因: "***+[NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:]: 无法在前导/尾随特性和向右/向左特性之间进行约束。 对两者使用前导/尾随,或两者都不使用。"

iOS 9 强制实施布局以使用向右前导尾随属性,但不能同时使用这两个属性。 为了解决此问题,请更改所有布局约束,使用 Storyboard 文件中设置的相同特性。

有关详细信息,请参阅 Stack Overflow 上关于 iOS 9 约束错误的讨论。

错误 ITMS-90535:意外的 CFBundleExecutable 密钥

从使用在 iOS 8(或更低版本)上编译和运行的第三方组件(尤其是我们的现有 Google 地图组件)的应用切换到 iOS 9 之后,当尝试将新版本提交到 iTunes Connect 时,可能会遇到以下形式的错误:

错误 ITMS-90535: 意外的 CFBundleExecutable 密钥. "Payload/app-name.app/component.bundle" 上的捆绑包中没有捆绑包可执行文件...

要解决此问题,通常可在项目中查找命名捆绑包,然后就像错误消息所建议的那样,通过删除 CFBundleExecutable 键来编辑捆绑包中的 Info.plist。 还应将 CFBundlePackageType 键设置为 BNDL

进行这些更改后,请清理并重新生成整个项目。 进行这些更改后,可以提交到 iTunes Connect,而不会出现问题。

有关详细信息,请参阅此 Stack Overflow 讨论。

CFNetwork SSLHandshake 失败 (-9824) 错误

尝试直接或从 iOS 9 中的 Web 视图连接到 Internet 时,可能会收到以下格式的错误:

2015-09-04 14:38:05.757 FormsWebViewiOS[2553:30362] CFNetwork SSLHandshake failed (-9824)
2015-09-04 14:38:05.758 FormsWebViewiOS[2553:30363] NSURLSession/NSURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9824)

或者以下形式的错误:

2015-09-04 14:39:17.881 FormsWebViewiOS[2568:30974] App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure.
Temporary exceptions can be configured via your app's Info.plist file.

在 iOS9 中,应用传输安全性 (ATS) 会强制实现 Internet 资源(例如应用的后端服务器)与应用之间的安全连接。 此外,ATS 要求使用 HTTPS 协议和高级 API 通信进行通信,以便使用前向保密的 TLS 版本 1.2 进行加密。

由于为 iOS 9 和 OS X 10.11 (El Capitan) 生成的应用中默认启用了 ATS,因此使用 NSURLConnectionCFURLNSURLSession 的所有连接都受 ATS 安全要求的约束。 如果连接不符合这些要求,它们将失败并出现异常。

若要了解如何解决此问题,请参阅应用传输安全指南的选择退出 ATS 部分。

我的现有应用未在 iOS 9 上运行

若要了解如何重新生成和重新部署现有应用以在 iOS 9 上运行,请参阅我们的 iOS 9 兼容性信息

构造函数中的 UICollectionViewCell.ContentView 为 Null

原因:在 iOS 9 中,initWithFrame: 构造函数现在是必需的,因为 iOS 9 中的行为更改,如 UICollectionView 文档所述 如果为指定的标识符注册了类,并且必须创建新单元格,则现在会通过调用其 initWithFrame: 方法初始化该单元格。

修复: 添加如下所示的 initWithFrame: 构造函数:

[Export ("initWithFrame:")]
public YourCellClassName (CGRect frame) : base (frame)
{
    Initialize (); // refactor initialize code into a method
}

相关示例:MotionGraphTextKitDemo

从 Xib/Nib 加载视图时,UIView 无法使用编码器进行初始化

原因:从 Interface Builder Xib 文件加载视图时会调用 initWithCoder: 构造函数。 如果未导出此构造函数,非托管代码无法调用其托管版本。 以前(例如在 iOS 8 中),会调用 IntPtr 构造函数来初始化视图。

修复: 创建和导出 initWithCoder: 构造函数,如下所示:

[Export ("initWithCoder:")]
public YourClassName (NSCoder coder) : base (coder)
{
    Initialize (); // refactor initialize code into a method
}

相关示例:聊天

Dyld 消息:没有名称的缓存映像...

在日志中可能会遇到以下信息的崩溃:

Dyld Error Message:
Dyld Message: no cach image with name (/System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore)

原因:这是 Apple 本机链接器中的一个 bug,当它们公开专用框架(在 iOS 7 中公开 JavaScriptCore 之前,它是专用框架),并且应用的部署目标是框架处于专用状态的 iOS 版本。 在这种情况下,Apple 的链接器将链接到框架的专用版本,而不是公共版本。

修复: 这将针对 iOS 9 进行寻址,但在此期间,可以自行应用一个简单的解决方法:仅针对项目中的更高 iOS 版本(在本例中可以尝试 iOS 7)。 其他框架可能表现出类似的问题,例如 WebKit 框架在 iOS 8 中公开(因此面向 iOS 7 将导致此错误;应将 iOS 8 定向到应用中使用 WebKit)。

不受信任的企业开发人员

尝试在实际 iOS 硬件上运行 Xamarin.iOS 应用的 iOS 9 版本时,可能会收到一条消息,指出你的开发人员帐户在设备上不受信任。 例如:

不受信任的企业开发人员警报

要解决此问题,请执行以下操作:

  1. 在开发 Mac 上启动 Xcode (最新 beta 版本)。

  2. 从“窗口”菜单中选择“设备”以打开“设备”窗口:

    “设备”窗口

  3. 在“设备”端面板中,选择你的设备,右键单击并选择“显示预配配置文件...”:

    SShow 预配配置文件

  4. 选择设备上当前存在的每个预配配置文件,然后选择 - 按钮来将其删除:

    删除预配配置文件

  5. 从“Xcode”菜单中选择“首选项...”和“帐户”:

    Xcode 帐户首选项

  6. 单击“查看详细信息...”按钮,然后选择“全部下载”按钮:

    下载所有配置文件

  7. 列表更新完毕后,选择“完成”按钮并关闭“首选项”窗口。

  8. 从 iOS 设备中删除尝试测试的 Xamarin.iOS 应用的现有版本。

  9. 返回到 Visual Studio for Mac,执行干净生成,然后尝试在设备上重新运行应用。

在看到 Xcode 加载的新的预配配置文件之前,可能需要停止再重启 Visual Studio for Mac。 你可能还需要调整 Xamarin.iOS 应用的“iOS 捆绑包签名”选项,选择新的预配配置文件。

启动屏幕问题

iOS 9 现在强制实施启动屏幕要求,以便不再重用相同的启动图像来支持不同的界面方向。 有关详细信息,请查看 Apple 的 UILanchImage 参考

(可选)可以使用 storyboard 文件来呈现应用的启动屏幕,而不是使用一组 .png 图像文件。 这是 Apple 提供启动屏幕的首选方法。 有关详细信息,请参阅我们的统一 Storyboard 简介指南。

最后,你的应用必须使用 storyboard 文件来展示其启动屏幕,并支持所有四个界面方向(纵向、反置纵向、横向向左和横向向右)以考虑在“侧拉窗口”面板或“拆分视图”模式下运行。 要详细了解 iOS 9 的新多任务处理功能,请参阅我们的 iPad 多任务处理指南。

NSInternalInconsistencyException 异常

编译并运行适用于 iOS 9 的现有 Xamarin.iOS 应用时,可能会收到以下形式的错误:

引发 Objective-C 异常。 名称: NSInternalInconsistencyException 原因: 应用程序窗口预期在应用程序启动结束时具有根视图控制器

由于应用窗口预计在应用程序启动结束时具有根视图控制器,而现有应用没有,则会引发此错误。

此问题至少有两种可能的解决方法:

  1. 更新应用来使用 storyboard 文件而不是 xib 文件定义其用户界面。 这需要大量的时间来更正,这取决于应用的大小以及关于如何使用 Xcode Interface Builder 设置 storyboard 部署的了解。 有关详细信息,请参阅我们的统一情节提要简介文档。
  2. AppDelegate 类中的 FinishedLaunching 方法中设置应用窗口的 RootViewController 属性,以指向应用 UI 中的视图控制器。

何时初始化视图和视图控制器

使用 Xamarin.iOS 时,可以在构造函数内初始化视图或视图控制器,这些构造函数在托管代码中公开内容时调用,但这会中断 iOS 设计。

通常,不应初始化任何可从构造函数回调 Objective-C 代码的内容,因为无法确定何时调用它。 这也意味着有一个更好的为止(其他 .ctor)或对重写的调用(由于 Objective-C 没有任何事件),在这种情况下,应进行此初始化。