将较旧的 Xamarin 解决方案更新到统一 API 时,可能会遇到以下错误。
NSInvalidArgumentException 找不到情节提要错误
使用自动迁移工具将项目转换为统一 API 后,Visual Studio for Mac 的当前版本中会出现一个 bug。 更新后,如果窗体中收到错误消息:
Objective-C exception thrown. Name: NSInvalidArgumentException Reason: Could not find a storyboard named 'xxx' in bundle NSBundle...
可以执行以下操作来解决此问题,找到以下生成目标文件:
/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/lib/mono/2.1/Xamarin.iOS.Common.targets
在此文件中,需要找到以下目标声明:
<Target Name="_CopyContentToBundle"
        Inputs = "@(_BundleResourceWithLogicalName)"
        Outputs = "@(_BundleResourceWithLogicalName -> '$(_AppBundlePath)%(LogicalName)')" >
并向其添加 DependsOnTargets="_CollectBundleResources" 属性。 类似于下面这样:
<Target Name="_CopyContentToBundle"
        DependsOnTargets="_CollectBundleResources"
        Inputs = "@(_BundleResourceWithLogicalName)"
        Outputs = "@(_BundleResourceWithLogicalName -> '$(_AppBundlePath)%(LogicalName)')" >
保存文件,重新启动 Visual Studio for Mac,并清理并重新生成项目。 Xamarin 应很快发布此问题的修补程序。
有用的使用技巧
使用迁移工具后,仍可能会收到一些需要手动干预的编译器错误。 可能需要手动修复的一些事项包括:
- 比较 - enums 可能需要- (int)强制转换。
- NSDictionary.IntValue现在返回一个- nint,有一个- Int32Value可以改用。
- nfloat不能标记- const类型- nint;- static readonly nint是一种合理的替代方法。
- 以前直接在命名空间中 - MonoTouch.的东西现在通常位于命名空间中- ObjCRuntime.(例如:- MonoTouch.Constants.Version现在- ObjCRuntime.Constants.Version)。
- 序列化对象的代码在尝试序列化 - nint和- nfloat类型时可能会中断。 请务必检查迁移后序列化代码按预期工作。
- 有时,自动化工具会错过条件编译器指令中的 - #if #else代码。 在这种情况下,需要手动进行修复(请参阅下面的常见错误)。
- 使用手动导出的方法 - [Export]可能无法由迁移工具自动修复,例如,在此代码 snippert 中,必须手动将返回类型更新为- nfloat:- [Export("tableView:heightForRowAtIndexPath:")] public nfloat HeightForRow(UITableView tableView, NSIndexPath indexPath)
- 统一 API 不提供 NSDate 和 .NET DateTime 之间的隐式转换,因为它不是无损失转换。 在强制转换为 - NSDate之前,防止与将 .NET- DateTime转换为本地或 UTC 相关的- DateTimeKind.Unspecified错误。
- Objective-C 类别方法现在在统一 API 中生成为扩展方法。 例如,以前使用 - UIView.DrawString的代码现在将在统一 API 中引用- NSString.DrawString。
- 使用 AVFoundation 类 - VideoSettings的代码应更改为使用- WeakVideoSettings属性。 这需要一个- Dictionary,该属性可用作设置类的属性,例如:- vidrec.WeakVideoSettings = new AVVideoSettings() { ... }.Dictionary;
- NSObject - .ctor(IntPtr)构造函数已从公共更改为受保护(以防止不当使用)。
- NSAction已 替换为 标准 .NET- Action。 一些简单的(单参数)委托也已- Action<T>替换为 。
最后,请参阅 经典 v 统一 API 差异 ,在代码中查找 API 的更改。 搜索 此页面 有助于查找经典 API 及其已更新的内容。
注意
迁移后命名空间 MonoTouch.Dialog 保持不变。 如果代码使用 MonoTouch.Dialog,则应继续使用该命名空间 - 请勿更改为 MonoTouch.DialogDialog!
常见编译器错误
下面列出了常见错误的其他示例,以及解决方案:
错误 CS0012:未引用的程序集中定义了类型“MonoTouch.UIKit.UIView”。
修复:这通常意味着项目引用尚未使用统一 API 生成的组件或 NuGet 包。 应删除并重新添加所有组件和 NuGet 包。 如果未修复此错误,则外部库可能尚不支持统一 API。
错误 MT0034:不能在同一 Xamarin.iOS 项目中同时包含“monotouch.dll”和“Xamarin.iOS.dll” - 显式引用“Xamarin.iOS.dll”,而“monotouch.dll”则由“Xamarin.Mobile,Version=0.6.3.0,Culture=neutral,PublicKeyToken=null”引用。
修复:删除导致此错误并重新添加到项目的组件。
错误 CS0234:命名空间“MonoTouch”中不存在类型或命名空间名称“Foundation”。 是否缺少程序集引用?
修复:Visual Studio for Mac 中的自动迁移工具应更新所有MonoTouch.FoundationFoundation引用,但在某些情况下,需要手动更新这些引用。 以前包含 MonoTouch的其他命名空间可能会出现类似的错误,例如 UIKit。
错误 CS0266:无法将类型“double”隐式转换为“System.float”
修复:更改类型和强制转换为 nfloat。 对于具有 64 位等效项的其他类型(例如 nint,)也可能发生此错误
nfloat scale = (nfloat)Math.Min(rect.Width, rect.Height);
错误 CS0266:无法将类型“CoreGraphics.CGRect”隐式转换为“System.Drawing.RectangleF”。 存在显式转换(是否缺少强制转换?)
修复:将实例更改为RectangleFCGRect、SizeF更改为CGSize和PointF更改为CGPoint。 using System.Drawing;命名空间应替换为using CoreGraphics;(如果尚不存在)。
错误 CS1502:“CoreGraphics.CGContext.SetLineDash”的最佳重载方法匹配(System.nfloat, System.nfloat[])具有一些无效的参数
修复:将数组类型更改为 nfloat[] 显式强制转换 Math.PI。
grphc.SetLineDash (0, new nfloat[] { 0, 3 * (nfloat)Math.PI });
错误 CS0115:“WordsTableSource.RowsInSection(UIKit.UITableView, int)”被标记为替代,但没有找到合适的替代方法
修复:将返回值和参数类型更改为 nint。 这通常发生在方法重写中,例如 onUITableViewSource、RowsInSection、NumberOfSections、GetHeightForRowTitleForHeader、 GetViewForHeader等。
public override nint RowsInSection (UITableView tableview, nint section) {
错误 CS0508:: WordsTableSource.NumberOfSections(UIKit.UITableView)返回类型必须为“System.nint”才能匹配重写成员 UIKit.UITableViewSource.NumberOfSections(UIKit.UITableView)
修复:当返回类型更改为 nint时,将返回值强制转换为 nint。
public override nint NumberOfSections (UITableView tableView)
{
    return (nint)navItems.Count;
}
错误 CS1061:类型“CoreGraphics.CGPath”不包含“AddElipseInRect”的定义
修复:将拼写更正为 AddEllipseInRect. 其他名称更改包括:
- 将“Color.Black”更改为 NSColor.Black.
- 将 MapKit“AddAnnotation”更改为 AddAnnotations.
- 将 AVFoundation“DataUsingEncoding”更改为 Encode.
- 将 AVFoundation 'AVMetadataObject.TypeQRCode' 更改为 AVMetadataObjectType.QRCode.
- 将 AVFoundation“Video设置”更改为 WeakVideoSettings.
- 将 PopViewControllerAnimated 更改为 PopViewController.
- 将 CoreGraphics “CGBitmapContext.SetRGBFillColor” 更改为 SetFillColor.
错误 CS0546:无法重写,因为“MapKit.MKAnnotation.Coordinate”没有可重写集访问器(CS0546)
通过子类化 MKAnnotation 创建自定义批注时,“坐标”字段没有 setter,只有 getter。
修复方法
- 添加字段以跟踪坐标
- 在“坐标”属性的 getter 中返回此字段
- 重写 SetCoordinate 方法并设置字段
- 使用传入坐标参数在函数中调用 SetCoordinate
该属性应与下面类似:
class BasicPinAnnotation : MKAnnotation
{
    private CLLocationCoordinate2D _coordinate;
    public override CLLocationCoordinate2D Coordinate
    {
        get
        {
            return _coordinate;
        }
    }
    public override void SetCoordinate(CLLocationCoordinate2D value)
    {
        _coordinate = value;
    }
    public BasicPinAnnotation (CLLocationCoordinate2D coordinate)
    {
        SetCoordinate(coordinate);
    }
}