Baca dalam bahasa Inggris

Bagikan melalui


Ketik registrar untuk Xamarin.iOS

Dokumen ini menjelaskan sistem pendaftaran jenis yang digunakan oleh Xamarin.iOS.

Pendaftaran kelas dan metode terkelola

Selama startup, Xamarin.iOS akan mendaftar:

Misalnya, pertimbangkan metode terkelola Main yang umum dalam aplikasi Xamarin.iOS:

C#
UIApplication.Main (args, null, "AppDelegate");

Kode ini memberi tahu Objective-C runtime untuk menggunakan jenis yang disebut AppDelegate sebagai kelas delegasi aplikasi. Objective-C Agar runtime dapat membuat instans kelas C#AppDelegate, kelas tersebut harus didaftarkan.

Xamarin.iOS melakukan pendaftaran secara otomatis, baik pada runtime (pendaftaran dinamis) atau pada waktu kompilasi (pendaftaran statis).

Pendaftaran dinamis menggunakan refleksi saat startup untuk menemukan semua kelas dan metode untuk mendaftar, meneruskannya ke Objective-C runtime. Pendaftaran dinamis digunakan secara default untuk build simulator.

Pendaftaran statis memeriksa, pada waktu kompilasi, rakitan yang digunakan oleh aplikasi. Ini menentukan kelas dan metode untuk mendaftar Objective-C dan menghasilkan peta, yang disematkan ke dalam biner Anda. Kemudian, saat startup, ia mendaftarkan peta dengan Objective-C runtime. Pendaftaran statis digunakan untuk build perangkat.

Kategori

Dimulai dengan Xamarin.iOS 8.10, dimungkinkan untuk membuat Objective-C kategori menggunakan sintaks C#.

Untuk membuat kategori, gunakan [Category] atribut dan tentukan jenis yang akan diperluas. Misalnya, kode berikut memperluas NSString:

C#
[Category (typeof (NSString))]

Masing-masing metode kategori memiliki [Export] atribut , membuatnya tersedia untuk Objective-C runtime:

C#
[Export ("today")]
public static string Today ()
{
    return "Today";
}

Semua metode ekstensi terkelola harus statis, tetapi dimungkinkan untuk membuat Objective-C metode instans menggunakan sintaks C# standar untuk metode ekstensi:

C#
[Export ("toUpper")]
public static string ToUpper (this NSString self)
{
    return self.ToString ().ToUpper ();
}

Argumen pertama untuk metode ekstensi adalah instans tempat metode dipanggil:

C#
[Category (typeof (NSString))]
public static class MyStringCategory
{
    [Export ("toUpper")]
    static string ToUpper (this NSString self)
    {
        return self.ToString ().ToUpper ();
    }
 }

Contoh ini akan menambahkan metode instans asli toUpper ke NSString kelas . Metode ini dapat dipanggil dari Objective-C:

C#
[Category (typeof (UIViewController))]
public static class MyViewControllerCategory
{
    [Export ("shouldAutoRotate")]
    static bool GlobalRotate ()
    {
        return true;
    }
}

Protokol

Dimulai dengan Xamarin.iOS 8.10, antarmuka dengan [Protocol] atribut akan diekspor sebagai Objective-C protokol:

C#
[Protocol ("MyProtocol")]
interface IMyProtocol
{
    [Export ("method")]
    void Method ();
}

class MyClass : IMyProtocol
{
    void Method ()
    {
    }
}

Kode ini diekspor IMyProtocol sebagai Objective-C protokol yang disebut MyProtocol dan kelas yang disebut MyClass yang mengimplementasikan protokol.

Sistem pendaftaran baru

Dimulai dengan versi 6.2.6 yang stabil dan versi beta 6.3.4, kami telah menambahkan statis registrarbaru . Dalam versi 7.2.1, kami membuat default baru registrar .

Sistem pendaftaran baru ini menawarkan fitur baru berikut:

  • Deteksi kompilasi-waktu kesalahan programmer:

    • Dua kelas didaftarkan dengan nama yang sama.
    • Lebih dari satu metode yang diekspor untuk merespons pemilih yang sama
  • Penghapusan kode asli yang tidak digunakan:

    • Sistem pendaftaran baru akan menambahkan referensi yang kuat ke kode yang digunakan dalam pustaka statis, memungkinkan linker asli untuk menghapus kode asli yang tidak digunakan dari biner yang dihasilkan. Pada pengikatan sampel Xamarin, sebagian besar aplikasi menjadi setidaknya 300k lebih kecil.
  • Dukungan untuk subkelas NSObjectgenerik ; lihat NSObject Generics untuk informasi selengkapnya. Selain itu, sistem pendaftaran baru akan menangkap konstruksi generik yang tidak didukung yang sebelumnya akan menyebabkan perilaku acak pada runtime.

Kesalahan yang tertangkap oleh yang baru registrar

Di bawah ini adalah beberapa contoh kesalahan yang ditangkap oleh yang baru registrar.

  • Mengekspor pemilih yang sama lebih dari sekali di kelas yang sama:

    C#
    [Register]
    class MyDemo : NSObject
    {
        [Export ("foo:")]
        void Foo (NSString str);
        [Export ("foo:")]
        void Foo (string str)
    }
    
  • Mengekspor lebih dari satu kelas terkelola dengan nama yang sama Objective-C :

    C#
    [Register ("Class")]
    class MyClass : NSObject {}
    
    [Register ("Class")]
    class YourClass : NSObject {}
    
  • Mengekspor metode generik:

    C#
    [Register]
    class MyDemo : NSObject
    {
        [Export ("foo")]
        void Foo<T> () {}
    }
    

Batasan baru registrar

Beberapa hal yang perlu diingat tentang yang baru registrar:

  • Beberapa pustaka pihak ketiga harus diperbarui untuk bekerja dengan sistem pendaftaran baru. Lihat modifikasi yang diperlukan di bawah ini untuk detail selengkapnya.

  • Kelemahan jangka pendek juga adalah bahwa Clang harus digunakan jika kerangka kerja Akun digunakan (ini karena header accounts.h Apple hanya dapat dikompilasi oleh Clang). Tambahkan --compiler:clang ke argumen mtouch tambahan untuk menggunakan Clang jika Anda menggunakan Xcode 4.6 atau yang lebih lama (Xamarin.iOS akan secara otomatis memilih Clang di Xcode 5.0 atau yang lebih baru.)

  • Jika Xcode 4.6 (atau yang lebih lama) digunakan, GCC/G++ harus dipilih jika nama jenis yang diekspor berisi karakter non-ASCII (ini karena versi Clang yang dikirim dengan Xcode 4.6 tidak mendukung karakter non-ASCII di dalam pengidentifikasi dalam Objective-C kode). Tambahkan --compiler:gcc ke argumen mtouch tambahan untuk menggunakan GCC.

Memilih registrar

Anda dapat memilih yang berbeda registrar dengan menambahkan salah satu opsi berikut ke argumen mtouch tambahan di pengaturan Build iOS proyek:

  • --registrar:static – default untuk build perangkat
  • --registrar:dynamic – default untuk build simulator

Catatan

API Klasik Xamarin mendukung opsi lain seperti --registrar:legacystatic dan --registrar:legacydynamic. Namun, opsi ini tidak didukung oleh API Terpadu.

Kekurangan dalam sistem pendaftaran lama

Sistem pendaftaran lama memiliki kelemahan berikut:

  • Tidak ada referensi statis (asli) ke Objective-C kelas dan metode di pustaka asli pihak ketiga, yang berarti bahwa kami tidak dapat meminta linker asli untuk menghapus kode asli pihak ketiga yang sebenarnya tidak digunakan (karena semuanya akan dihapus). Ini adalah alasan untuk -force_load libNative.a bahwa setiap pengikatan pihak ketiga harus dilakukan (atau yang setara ForceLoad=true dalam [LinkWith] atribut).
  • Anda dapat mengekspor dua jenis terkelola dengan nama yang sama Objective-C tanpa peringatan. Skenario yang jarang terjadi adalah berakhir dengan dua AppDelegate kelas di namespace yang berbeda. Pada runtime itu akan sepenuhnya acak mana yang dipilih (pada kenyataannya, itu bervariasi antara eksekusi aplikasi yang bahkan tidak dibangun kembali - yang dibuat untuk pengalaman debugging yang sangat membingungkan dan membuat frustrasi).
  • Anda dapat mengekspor dua metode dengan tanda tangan yang sama Objective-C . Namun sekali lagi yang akan dipanggil dari Objective-C itu acak (tetapi masalah ini tidak sama umumnya dengan yang sebelumnya, sebagian besar karena satu-satunya cara untuk benar-benar mengalami bug ini adalah dengan mengambil alih metode terkelola yang tidak beruntung).
  • Set metode yang diekspor sedikit berbeda antara build dinamis dan statis.
  • Ini tidak berfungsi dengan baik ketika mengekspor kelas generik (yang tepat implementasi generik yang dijalankan pada runtime akan acak, secara efektif mengakibatkan perilaku yang tidak ditentukan).

Baru registrar: perubahan yang diperlukan pada pengikatan

Bagian ini menjelaskan perubahan pengikatan yang harus dilakukan untuk bekerja dengan yang baru registrar.

Protokol harus memiliki atribut [Protokol]

Protokol sekarang harus memiliki [Protocol] atribut . Jika Anda tidak melakukan ini, Anda akan mengalami kesalahan linker asli seperti:

Console
Undefined symbols for architecture i386: "_OBJC_CLASS_$_ProtocolName", referenced from: ...

Pemilih harus memiliki jumlah parameter yang valid

Semua pemilih harus menunjukkan jumlah parameter dengan benar. Sebelumnya, kesalahan ini diabaikan dan dapat menyebabkan masalah runtime.

Singkatnya, jumlah titik dua harus cocok dengan jumlah parameter:

  • Tidak ada parameter: foo
  • Satu parameter: foo:
  • Dua parameter: foo:parameterName2:

Berikut ini adalah penggunaan yang salah:

C#
// Invalid: export takes no arguments, but function expects one
[Export ("apply")]
void Apply (NSObject target);

// Invalid: exported as taking an argument, but the managed version does not have one:
[Export ("display:")]
void Display ();

Gunakan parameter IsVariadic dalam Ekspor

Fungsi variadik harus menggunakan IsVariadic argumen ke [Export] atribut :

C#
[Export ("variadicMethod:", IsVariadic = true)]
void VariadicMethod (NSObject first, IntPtr subsequent);

Tidak mungkin untuk mengikat kelas yang tidak ada di pustaka asli. Jika kelas telah dihapus dari atau diganti namanya di pustaka asli, pastikan untuk memperbarui pengikatan agar cocok.