共用方式為


將程式碼更新至 Unified API 的祕訣

將舊版 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 發行。

有用的 提示

使用移轉工具之後,您仍可能會收到一些需要手動介入的編譯程序錯誤。 可能需要手動修正的一些事項包括:

  • enum比較 s 可能需要(int)轉型。

  • NSDictionary.IntValue 現在會傳 nint回 ,有 Int32Value 可以改用的 。

  • nfloatnint 型別無法標示 const; static readonly nint 是合理的替代方式。

  • 在命名空間中 MonoTouch. 直接使用的項目現在通常位於 命名空間中 ObjCRuntime. (例如: MonoTouch.Constants.Version 現在 ObjCRuntime.Constants.Version為 )。

  • 串行化物件的程式代碼可能會在嘗試串行化 nintnfloat 型別時中斷。 請務必檢查您的串行化程式代碼在移轉後如預期般運作。

  • 有時候自動化工具會遺漏條件式編譯程式指示詞內的 #if #else 程序代碼。 在此情況下,您必須手動進行修正(請參閱下面的常見錯誤)。

  • 使用 手動匯出的方法 [Export] 可能無法由移轉工具自動修正,例如,在此程式代碼 snippert 中,您必須手動將傳回型別更新為 nfloat

    [Export("tableView:heightForRowAtIndexPath:")]
    public nfloat HeightForRow(UITableView tableView, NSIndexPath indexPath)
    
  • 整合 API 不會提供 NSDate 與 .NET DateTime 之間的隱含轉換,因為它不是不遺失的轉換。 若要避免將 .NET DateTime 轉換成本機或 UTC 的相關錯誤DateTimeKind.Unspecified,再轉換成 NSDate

  • 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.Foundation 參考 Foundation,但在某些情況下,這些參考必須手動更新。 先前包含 MonoTouch的其他命名空間可能會出現類似的錯誤,例如 UIKit

錯誤 CS0266:無法隱含地將類型 'double' 轉換為 'System.float'

修正:變更類型並轉換成 nfloat。 其他具有 64 位對等專案的型別也可能發生此錯誤(例如 nint, )

nfloat scale = (nfloat)Math.Min(rect.Width, rect.Height);

錯誤 CS0266:無法隱含地將類型 'CoreGraphics.CGRect' 轉換為 'System.Drawing.RectangleF'。 存在明確的轉換 (是否遺漏轉型?)

修正:將實體變更為 RectangleFCGRectSizeFCGSize將與 PointF 變更為 CGPointusing System.Drawing;命名空間應該取代為 using CoreGraphics; (如果尚未存在的話)。

error 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。 這通常發生在方法覆寫中,例如 、UITableViewSourceRowsInSectionNumberOfSectionsGetHeightForRowTitleForHeaderGetViewForHeader等上的覆寫。

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 方法並設定欄位
  • 使用傳入座標參數在 ctor 中呼叫 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);
    }
}