將程式碼更新至 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
可以改用的 。nfloat
和nint
型別無法標示const
;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 之間的隱含轉換,因為它不是不遺失的轉換。 若要避免將 .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
已 取代 為標準 .NETAction
。 某些簡單(單一參數)委派也已取代為Action<T>
。
最後,請參閱 傳統 v 整合 API 差異 ,以查閱程式代碼中 API 的變更。 搜尋 此頁面 可協助尋找傳統 API 及其已更新的內容。
注意
移 MonoTouch.Dialog
轉之後,命名空間會維持不變。 如果您的程式代碼使用 MonoTouch.Dialog,您應該繼續使用該命名空間 - 請勿變更MonoTouch.Dialog
為 Dialog
!
常見的編譯程序錯誤
下列列出常見錯誤的其他範例,以及解決方案:
錯誤 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'。 存在明確的轉換 (是否遺漏轉型?)
修正:將實體變更為 RectangleF
CGRect
、 SizeF
CGSize
將與 PointF
變更為 CGPoint
。 using 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
。 這通常發生在方法覆寫中,例如 、UITableViewSource
、RowsInSection
NumberOfSections
、GetHeightForRow
、TitleForHeader
、 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 方法並設定欄位
- 使用傳入座標參數在 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);
}
}