Objective-C Přehled vazeb
Podrobnosti o fungování procesu vazby
Vytvoření vazby Objective-C knihovny pro použití s Xamarinem provede tři kroky:
Napište "definici rozhraní API" jazyka C#, která popisuje, jak je nativní rozhraní API vystaveno v .NET a jak se mapuje na podkladový Objective-C. To se provádí pomocí standardních konstruktorů jazyka C# jako
interface
a různých atributů vazby (viz tento jednoduchý příklad).Jakmile napíšete "definici rozhraní API" v jazyce C#, zkompilujete ho tak, aby vytvořilo sestavení "binding". To lze provést na příkazovém řádku nebo pomocí vazbového projektu v Visual Studio pro Mac nebo sadě Visual Studio.
Toto sestavení "binding" se pak přidá do projektu aplikace Xamarin, abyste měli přístup k nativním funkcím pomocí rozhraní API, které jste definovali. Projekt vazby je zcela oddělený od projektů aplikace.
Poznámka:
Krok 1 lze automatizovat pomocí Objective Sharpie. Prozkoumá Objective-C rozhraní API a vygeneruje navrženou definici rozhraní API v jazyce C#. Soubory vytvořené Objective Sharpie můžete přizpůsobit a použít je v projektu vazby (nebo na příkazovém řádku) k vytvoření sestavení vazby. Objective Sharpie sama o sobě nevytová vazby, je to jen volitelná část většího procesu.
Můžete si také přečíst další technické podrobnosti o tom, jak to funguje, což vám pomůže se zápisem vazeb.
Vazby příkazového řádku
K přímému btouch-native
sestavení vazeb můžete použít Xamarin.iOS (nebo bmac-native
pokud používáte Xamarin.Mac). Funguje předáním definic rozhraní API jazyka C#, které jste vytvořili ručně (nebo pomocí Objective Sharpie) do nástroje příkazového řádku (btouch-native
pro iOS nebo bmac-native
pro Mac).
Obecná syntaxe pro vyvolání těchto nástrojů je:
# Use this for Xamarin.iOS:
bash$ /Developer/MonoTouch/usr/bin/btouch-native -e cocos2d.cs -s:enums.cs -x:extensions.cs
# Use this for Xamarin.Mac:
bash$ bmac-native -e cocos2d.cs -s:enums.cs -x:extensions.cs
Výše uvedený příkaz vygeneruje soubor cocos2d.dll
v aktuálním adresáři a bude obsahovat plně vázanou knihovnu, kterou můžete použít v projektu. Toto je nástroj, který Visual Studio pro Mac používá k vytvoření vazeb, pokud používáte projekt vazby (popsaný níže).
Vytvoření vazby projektu
Projekt vazby lze vytvořit v Visual Studio pro Mac nebo sadě Visual Studio (Visual Studio podporuje pouze vazby pro iOS) a usnadňuje úpravu a vytváření definic rozhraní API pro vazbu (versus použití příkazového řádku).
Postupujte podle této úvodní příručky a zjistěte, jak vytvořit a použít projekt vazby k vytvoření vazby.
Objective Sharpie
Objective Sharpie je další samostatný nástroj příkazového řádku, který pomáhá s počátečními fázemi vytváření vazby. Nevytváří vazbu sama o sobě, ale automatizuje počáteční krok generování definice rozhraní API pro cílovou nativní knihovnu.
Přečtěte si dokumentaci Objective Sharpie a zjistěte, jak analyzovat nativní knihovny, nativní architektury a CocoaPods do definic rozhraní API, které je možné integrovat do vazeb.
Jak funguje vazba
K ručnímu vytvoření vazby nových (dříve nevázaných) Objective-C typů je možné použít atribut [Register], atribut [Export] a ruční Objective-C vyvolání selektoru.
Nejprve vyhledejte typ, který chcete svázat. Pro účely diskuze (a jednoduchost) vytvoříme vazbu typu NSEnumerator (který již byl vázán v Foundation.NSEnumerator; implementace níže je určena pouze pro příklady).
Za druhé, musíme vytvořit typ C#. Pravděpodobně to budeme chtít umístit do oboru názvů; protože Objective-C obory názvů nepodporuje, budeme muset pomocí atributu [Register]
změnit název typu, který Xamarin.iOS zaregistruje Objective-C v modulu runtime. Typ C# musí také dědit ze foundation.NSObject:
namespace Example.Binding {
[Register("NSEnumerator")]
class NSEnumerator : NSObject
{
// see steps 3-5
}
}
Za třetí si projděte Objective-C dokumentaci a vytvořte instance ObjCRuntime.Selector pro každý selektor, který chcete použít. Umístěte je do těla třídy:
static Selector selInit = new Selector("init");
static Selector selAllObjects = new Selector("allObjects");
static Selector selNextObject = new Selector("nextObject");
Čtvrtý typ bude muset poskytnout konstruktory. Je nutné zřetězit volání konstruktoru do konstruktoru základní třídy. Atributy [Export]
umožňují Objective-C volání konstruktorů se zadaným názvem selektoru:
[Export("init")]
public NSEnumerator()
: base(NSObjectFlag.Empty)
{
Handle = Messaging.IntPtr_objc_msgSend(this.Handle, selInit.Handle);
}
// This constructor must be present so that Xamarin.iOS
// can create instances of your type from Objective-C code.
public NSEnumerator(IntPtr handle)
: base(handle)
{
}
Páté, zadejte metody pro každý selektor deklarovaný v kroku 3. Ty se použijí objc_msgSend()
k vyvolání selektoru v nativním objektu. Všimněte si použití runtime.GetNSObject() k převodu IntPtr
na odpovídající typ NSObject
(dílčí)typ. Pokud chcete, aby metoda byla voláná z Objective-C kódu, člen musí být virtuální.
[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));
}
}
Seskupování všech:
using System;
using Foundation;
using ObjCRuntime;
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));
}
}
}
}