绑定是怎样实现的--Xamarin.iOS
可以通过结合使用【Register】属性,【Export】属性,和手动调用Obj-C选择器来手动绑定新的Obj-C(之前未绑定过)类型。
第一 选一个你希望绑定的类型。
出于讨论的目的(及简便性),我们将选择绑定NSEnumerator 。(这个类型的绑定在Foundation.NSEnumerator中已经实现,以下对该类型的实现仅出于示例的目的)
第二 新建一个C#的类(类型)。
我们希望将这个类型置于某命名空间(namespace),由于Obj-C不支持命名空间,我们通过【Register】属性指定类型名称,Xamarin会注册到Obj-C运行时。
同样的,该C#类型需要继承Foundation.NSObject:
namespace Example.Binding {
[Register("NSEnumerator")]
class NSEnumerator : NSObject
{
// see steps 3-5
}
}
第三 查看下Obj-C 选择器的文档(译注1),为每一个你希望使用的选择器创建实例:
static Selector selInit = new Selector("init");
static Selector selAllObjects = new Selector("allObjects");
static Selector selNextObject = new Selector("nextObject");
第四 你的类型需要提供构造函数。
你需要链接(chain)你的构造函数到基类的构造函数。【Export】属性将允许Obj-C代码通过指定的选择器名称来调用你的构造函数:
[Export("init")]
public NSEnumerator()
: base(NSObjectFlag.Empty)
{
Handle = Messaging.IntPtr_objc_msgSend(this.Handle, selInit.Handle);
}
// 这个构造函数是必须的,这样Xamarin.iOS才能通过Obj-C代码来创建你的//类型的实例
public NSEnumerator(IntPtr handle)
: base(handle)
{
}
第五 为你在第三步中声明的选择器提供方法实现。
在原生代码中,这步其实是在使用 objc_msgSend()来调用(invoke 译注2)选择器。注意使用Runtime.GetNSObject() 来转换IntPtr到恰当的NSObject类型(其子类)。如果想Obj-C代码能调用,方法必须声明为虚方法:
[Export("nextObject")]
public virtual NSObject NextObject()
{
return Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend(this.Handle, selNextObject.Handle));
}
// 注意这里的[Export]属性是修饰get/set 方法:
public virtual NSArray AllObjects {
[Export("allObjects")]
get {
return (NSArray) Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend(this.Handle, selAllObjects.Handle));
}
}
namespace Example.Binding {
[Register("NSEnumerator")]
class NSEnumerator : NSObject
{
static Selector selInit = new Selector("init");
static Selector selAllObjects = new Selector("allObjects");
static Selector selNextObject = new Selector("nextObject");
[Export("init")]
public NSEnumerator()
: base(NSObjectFlag.Empty)
{
Handle = Messaging.IntPtr_objc_msgSend(this.Handle,
selInit.Handle);
}
public NSEnumerator(IntPtr handle)
: base(handle)
{
}
[Export("nextObject")]
public virtual NSObject NextObject()
{
return Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend(this.Handle,
selNextObject.Handle));
}
// Note that for properties, [Export] goes on the get/set method:
public virtual NSArray AllObjects {
[Export("allObjects")]
get {
return (NSArray) Runtime.GetNSObject(
Messaging.IntPtr_objc_msgSend(this.Handle,
selAllObjects.Handle));
}
}
}
}
命令行绑定
你可以直接使用Xamarin.iOS的btouch-native(使用 bmac-native如果你是Xamarin.Mac)来生成你的绑定。这也是Xamarin Studio用来创建绑定的工具。
使用语法如下:
# Use this for Xamarin.iOS:
bash$ /Developer/MonoTouch/usr/bin/btouch-native -e cocos2d.cs -s:enums.cs -x:extensions.cs
# Use this for MonoMac:
bash$ bmac-native -e cocos2d.cs -s:enums.cs -x:extensions.cs
译注1:关于Obj-C的选择器,推荐一篇中文文章:
Class类型,选择器Selector以及指针函数
译注2:Obj-C中对Selector的调用,术语叫 send message,而非invoke selector,是通过objc_msgSend 一族函数完成。
译注2:Obj-C中对Selector的调用,术语叫 send message,而非invoke selector,是通过objc_msgSend 一族函数完成。
(翻译自Xamarin官网 2015-11-2)