Xamarin IOS:如何绑定扩展特性



我开始在我的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
{
}

最新更新