registrar Xamarin.iOS için Tür

Bu belge, Xamarin.iOS tarafından kullanılan tür kayıt sistemini açıklar.

Yönetilen sınıfların ve yöntemlerin kaydı

Başlatma sırasında Xamarin.iOS şunları kaydedecek:

Örneğin, Main Xamarin.iOS uygulamalarında yaygın olarak kullanılan yönetilen yöntemi göz önünde bulundurabilirsiniz:

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

Bu kod, Objective-C çalışma zamanının uygulamanın temsilci sınıfı AppDelegate olarak adlandırılan türü kullanmalarını söyler. Çalışma Objective-C zamanının C# sınıfının bir örneğini oluşturabilecek AppDelegate olması için bu sınıfın kayıtlı olması gerekir.

Xamarin.iOS, kaydı çalışma zamanında (dinamik kayıt) veya derleme zamanında (statik kayıt) otomatik olarak gerçekleştirir.

Dinamik kayıt başlangıçta yansımayı kullanarak kaydedilen tüm sınıfları ve yöntemleri bulur ve bunları çalışma zamanlarına Objective-C iletir. Simülatör derlemeleri için varsayılan olarak dinamik kayıt kullanılır.

Statik kayıt, derleme zamanında uygulama tarafından kullanılan derlemeleri inceler. Ile kaydedilen sınıfları ve yöntemleri belirler ve ikili Objective-C dosyanıza eklenmiş bir eşleme üretir. Ardından, başlangıçta eşlemeyi çalışma zamanı ile Objective-C kaydedmektedir. Cihaz derlemeleri için statik kayıt kullanılır.

Kategoriler

Xamarin.iOS 8.10'dan başlayarak C# söz dizimi Objective-C kullanarak kategoriler oluşturmak mümkündür.

Bir kategori oluşturmak için özniteliğini [Category] kullanın ve genişletecek türü belirtin. Örneğin, aşağıdaki kod NSString genişletildi:

[Category (typeof (NSString))]

Bir kategorinin yöntemlerinin her biri bir [Export] özniteliğine sahip ve çalışma zamanı tarafından kullanılabilir Objective-C hale geldi:

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

Tüm yönetilen uzantı yöntemleri statik olmalıdır, ancak uzantı yöntemleri için standart C# söz dizimi kullanılarak Objective-C örnek yöntemleri oluşturmak mümkündür:

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

Genişletme yönteminin ilk bağımsız değişkeni, yönteminin çağrıldı olduğu örnektir:

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

Bu örnek, sınıfına toUpper bir yerel örnek yöntemi NSString ekler. Bu yöntem, yönteminden çağrıl Objective-C olabilir:

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

Protokoller

Xamarin.iOS 8.10'dan başlayarak, özniteliğine sahip arabirimler protokol [Protocol]Objective-C olarak 'ye dışarı aktarıldı:

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

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

Bu kod, IMyProtocol adlı bir protokol ve protokol Objective-CMyProtocol uygulayan adlı bir sınıf olarak dışarı MyClass aktarıyor.

Yeni kayıt sistemi

Kararlı 6.2.6 sürümü ve beta 6.3.4 sürümünden başlayarak yeni bir statik registrar ekledik. 7.2.1 sürümünde, yeni varsayılanı registrar yaptık.

Bu yeni kayıt sistemi aşağıdaki yeni özellikleri sunar:

  • Programcı hatalarının derleme zamanı algılaması:

    • Aynı adla kaydedilen iki sınıf.
    • Aynı seçiciye yanıt vermek için dışarı aktarıldı birden fazla yöntem
  • Kullanılmayan yerel kodun kaldırılması:

    • Yeni kayıt sistemi statik kitaplıklarda kullanılan koda güçlü başvurular ekler ve bu da yerel bağlantıcıya elde edilen ikili dosyadan kullanılmayan yerel kodu çıkartır. Xamarin'in örnek bağlamalarında çoğu uygulama en az 300 bin daha küçük hale geldi.
  • genel alt sınıfları için NSObject destek; daha fazla NSObject Adları. Buna ek olarak, yeni kayıt sistemi daha önce çalışma zamanında rastgele davranışa neden olan desteklenmeyen genel yapıları yakalar.

tarafından yakalanan hatalarla ilgili registrar

Aşağıda yeni tarafından yakalanan hatalara bazı örnekler registrar verilmiştir.

  • Aynı seçiciyi aynı sınıfta birden çok kez dışarı aktarma:

    [Register]
    class MyDemo : NSObject
    {
        [Export ("foo:")]
        void Foo (NSString str);
        [Export ("foo:")]
        void Foo (string str)
    }
    
  • Aynı adla birden fazla yönetilen sınıfı dışarı Objective-C aktarma:

    [Register ("Class")]
    class MyClass : NSObject {}
    
    [Register ("Class")]
    class YourClass : NSObject {}
    
  • Genel yöntemleri dışarı aktarma:

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

Sınırlamalar registrar

Yeni ile ilgili olarak göz gereken bazı registrar şeyler:

  • Bazı üçüncü taraf kitaplıkların yeni kayıt sistemiyle çalışacak şekilde güncelleştirilmiş olması gerekir. Diğer ayrıntılar için aşağıdaki gerekli değişikliklere bakın.

  • Kısa vadeli bir dezavantajı, Accounts çerçevesi kullanılıyorsa Clang'nin de kullanılmalıdır (bunun nedeni Apple'ın accounts.h üst bilgisi yalnızca Clang tarafından derlenmiş olmasıdır). Xcode 4.6 veya önceki bir sürüm kullanıyorsanız Clang'yi kullanmak için ek mtouch bağımsız değişkenlerine ekleyin --compiler:clang (Xamarin.iOS otomatik olarak Xcode 5.0 veya sonraki sürümlerinde Clang'yi seçer.)

  • Xcode 4.6 (veya önceki bir sürümü) kullanılıyorsa, dışarı aktaran tür adları ASCII olmayan karakterler içeriyorsa GCC/G++ seçilmelidir (bunun nedeni, Xcode 4.6 ile gönderilen Clang sürümünün kod içindeki tanımlayıcıların içinde ASCII olmayan karakterleri desteklememiş Objective-C olmasıdır). Diğer --compiler:gcc mtouch bağımsız değişkenlerini kullanarak GCC.

Seçerek registrar

Projenin iOS Derleme ayarlarında ek mtouch bağımsız değişkenlerine aşağıdaki seçeneklerden birini registrar ekleyerek farklı bir değer registrar

  • --registrar:static – cihaz derlemeleri için varsayılan
  • --registrar:dynamic – simülatör derlemeleri için varsayılan

Not

Xamarin'in Classic API ve gibi diğer seçenekleri --registrar:legacystatic--registrar:legacydynamic desteklemişti. Ancak, bu seçenekler aşağıdakiler tarafından Unified API.

Eski kayıt sistemiyle ilgili eksiklikler

Eski kayıt sisteminin aşağıdaki dezavantajları vardır:

  • Üçüncü taraf yerel kitaplıklarda sınıflara ve yöntemlere (yerel) statik başvuru yoktu, yani yerel bağlantıcıdan aslında kullanılmayan üçüncü taraf yerel kodu kaldırmalarını isteyemedik (çünkü her şey kaldırılacak). Objective-C Bu, her üçüncü taraf bağlamanın (veya özniteliğinde -force_load libNative.a eşdeğerini) ForceLoad=true yapmalarının [LinkWith] nedenidir.
  • Uyarı vermeden aynı adla iki yönetilen Objective-C türü dışarı aktarın. Nadir bir senaryo, farklı ad alanlarında iki AppDelegate sınıfa sahip olmaktır. Çalışma zamanında, hangisinin seçilene kadar tamamen rastgele olması gerekir (aslında, çok şaşırtıcı ve can sıkıcı bir hata ayıklama deneyimi için yapılan, daha önce bile yeniden oluşturulmuş bir uygulamanın çalıştırmaları arasında farklıydı).
  • Aynı imzaya sahip iki yöntemi dışarı Objective-C aktarın. Yine hangisinin rastgele olduğunu da ifade etmek gerekirse (ancak bu sorun önceki sorun kadar yaygın değildi çünkü bu hatayla gerçekten yaşamanın tek yolu şanssız yönetilen yöntemi geçersiz Objective-C kılmaktı).
  • Dışarı aktaran yöntem kümesi, dinamik ve statik derlemeler arasında biraz farklıydı.
  • Genel sınıflar dışarı aktarıldıklarında düzgün çalışmaz (çalışma zamanında yürütülen tam genel uygulama rastgele olur ve bu da belirlenemeyen davranışa neden olur).

registrar Yeni: bağlamalarda gerekli değişiklikler

Bu bölümde, yeni ile çalışmak için yapılacak bağlama değişiklikleri açık registrar almaktadır.

Protokoller [Protocol] özniteliğine sahip olmalı

Protokollerin artık özniteliğine sahip olması [Protocol] gerekir. Bunu yapmasanız, aşağıdakiler gibi bir yerel bağlantı hatası alırsınız:

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

Seçiciler geçerli sayıda parametreye sahip olmalıdır

Tüm seçicilerin parametre sayısını doğru şekilde belirterek belirt olması gerekir. Daha önce bu hatalar yoksayılıyor ve çalışma zamanı sorunlarına neden olabilir.

Kısacası iki nokta sayısının parametre sayısıyla eşleşmesi gerekir:

  • Parametre yok: foo
  • Bir parametre: foo:
  • İki parametre: foo:parameterName2:

Aşağıdakiler yanlış kullanımlardır:

// 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 ();

Dışarı Aktarma'da IsVariadic parametresini kullanma

Variadic işlevlerinin özniteliği için IsVariadic bağımsız değişken kullanması [Export] gerekir:

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

Yerel kitaplıkta mevcut olmayan sınıfları bağlamak mümkün değildir. Yerel kitaplıkta bir sınıf kaldırılmış veya yeniden adlandırılmışsa, bağlamaları eşleşmesi için güncelleştirin.