我开始在我的xamarin.ios项目中使用github的sdautolayout库。该库具有此Uiview类的许多扩展方法和属性。
我非常容易地构建了绑定项目。
但是,当我在项目中使用此lib时,我发现所有扩展属性在C#应用程序中均无用。
然后,如果我将Sd_layout
'S'get'属性更改为方法 -> SDAutoLayoutModel Sd_layout ();
,则运行时将引发例外:
未识别的选择器发送到类
[类别]
[baseType(typeof(uiview))]
接口uiview_sdautolayout
{
//-(sdautolayoutmodel *)sd_layout;
[静态]
[export(" sd_layout")]
sdautolayoutmodel sd_layout {get;}
..........
因此,我应该如何更改绑定项目中的扩展属性,并将其用作xamarin.ios
项目中的扩展方法
问题是属性/方法是[Static]
,并且在[Category]
上。绑定发生器试图使用扩展方法(需要实例)或扩展类型(由于它是Uikit类型,因此无法执行)。
非uikit基础类型
最简单的解决方案是强迫发电机尽可能多地做,然后您可以提供帮助。可能有更好的方法,但这有效。
首先,将所有[Static]
成员移至新类型(如果它们都是静态的,请跳过此类型)。最好使用用户友好的名称,因为它们实际上将键入此名称。在您的情况下,您可以使用SDAutoLayoutUIView
或其他东西。
然后,删除[Category]
属性,将[Static]
属性添加到 class ,并确保[BaseType]
属性在那里。
现在将创建有关class_ptr
不存在的编译器错误。这是因为类别期望发电机做某事,但由于某种原因,它没有...(听起来像一个错误。)
无论如何,只需使用一个成员创建一个小型类作为附加文件:
private static readonly IntPtr class_ptr = Class.GetHandle("UIView");
现在,一切都应该起作用。最终代码是Additions.cs
:
partial class SDAutoLayoutUIView
{
private static readonly IntPtr class_ptr = Class.GetHandle("UIView");
}
,您的绑定代码应该是:
// ...
[Category]
[BaseType(typeof(UIView))]
interface UIView_SDAutoLayout
{
// ... instance methods
}
[Static]
[BaseType(typeof(UIView))]
interface SDAutoLayoutUIView
{
// ... static methods
// -(SDAutoLayoutModel *)sd_layout;
[Static]
[Export("sd_layout")]
SDAutoLayoutModel Sd_layout ();
}
// ...
这应该做到。此选项很棒,因为我们只需要为整个方法做一行即可。如果只有一个或两个,那么这并不是一个很大的优势,而是工作更少。
Uikit基础类型
如果对象不从UIView
继承,则以上可以正常工作。这是因为发电机为Uikit类提供了额外的功能,以使外观绑定。
如果是这种情况,则必须保持生成的绑定,但将其保留为[Internal]
。这是更多信息:
https://github.com/xamarin/xamarin-macios/pull/1862
因此,您的绑定代码应该像这样(使用新的[Internal]
):
[Category]
[BaseType(typeof(UIView))]
interface UIView_SDAutoLayout
{
// -(SDAutoLayoutModel *)sd_layout;
[Static]
[Internal]
[Export("sd_layout")]
SDAutoLayoutModel Sd_layout();
}
但是,您的添加代码然后正确执行:
partial class UIView_SDAutoLayout
{
public static SDAutoLayoutModel Sd_layout()
{
// use the extension method
return (null as UIView).Sd_layout();
}
}
这起作用了,因为我们将用户隐藏了怪异的扩展方法,并将其包裹为不需要一些空值的不错的静态方法。有效地,这是工具的限制,因为它始终使用扩展方法进行类别,但是静态方法不能是C#中的扩展。
。注意:您可能想为课程使用一个好名字:SDAutoLayoutUIView
如果基本类型是Uikit类型,例如Uiview,这很棒。(这也适用于任何类型,并且不限于UIKIT类型。)但是,它确实需要将所有静态方法标记为内部,然后为每种方法创建正确的过载。如果您需要它们,这不是问题,而且通常没有很多事情要做。
拥有的基本类型
最好,最简单的情况是当您拥有基本类型时。例如,如果这是您的约束力:
[BaseType(typeof(UIView))]
interface MyThing
{
}
[Category]
[BaseType(typeof(MyThing))]
interface Others_MyThing
{
[Static]
[Export("createNewThing")]
MyThing CreateNewThing ();
}
在这种情况下,只需将成员移至非类别类型:
[BaseType(typeof(UIView))]
interface MyThing
{
[Static]
[Export("createNewThing")]
MyThing CreateNewThing ();
}
[Category]
[BaseType(typeof(MyThing))]
interface Others_MyThing
{
}