Aracılığıyla paylaş


Xamarin.iOS için tür registrar

Bu belgede Xamarin.iOS tarafından kullanılan tür kayıt sistemi açıklanmaktadır.

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

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

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

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

Bu kod çalışma zamanına Objective-C uygulamanın temsilci sınıfı olarak adlandırılan AppDelegate türü kullanmasını söyler. Çalışma zamanının Objective-C C# AppDelegate sınıfının bir örneğini oluşturabilmesi için bu sınıfın kaydedilmesi gerekir.

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

Dinamik kayıt, kaydetmeye yönelik tüm sınıfları ve yöntemleri bulmak için başlangıçta yansımayı kullanır ve bunları çalışma zamanına Objective-C geçirir. Dinamik kayıt, simülatör derlemeleri için varsayılan olarak kullanılır.

Statik kayıt derleme zamanında uygulama tarafından kullanılan derlemeleri inceler. Ile kaydedilecek Objective-C sınıfları ve yöntemleri belirler ve ikili dosyanıza eklenmiş bir harita oluşturur. Ardından başlangıçta eşlemeyi çalışma zamanına Objective-C kaydeder. Statik kayıt, cihaz derlemeleri için kullanılır.

Kategoriler

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

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

[Category (typeof (NSString))]

Bir kategorinin yöntemlerinin her birinin bir [Export] özniteliği vardır ve bu da çalışma zamanı için Objective-C kullanılabilir olmasını sağlar:

[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 dizimini kullanarak örnek yöntemleri oluşturmak Objective-C mümkündür:

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

Uzantı yönteminin ilk bağımsız değişkeni, yönteminin çağrıldığı ö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 NSString yerel toUpper bir örnek yöntemi ekler. Bu yöntem' den Objective-Cçağrılabilir:

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

Protokoller

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

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

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

Bu kod' a Objective-C adlı MyProtocol bir protokol ve protokolü uygulayan adlı MyClass bir sınıf olarak dışarı aktarırIMyProtocol.

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 registrarekledik. 7.2.1 sürümünde yeniyi registrar varsayılan olarak yaptık.

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

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

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

    • Yeni kayıt sistemi statik kitaplıklarda kullanılan koda güçlü başvurular ekleyerek yerel bağlayıcının kullanılmayan yerel kodu sonuçta elde edilen ikili dosyadan çıkarmasına olanak sağlar. Xamarin'in örnek bağlamalarında çoğu uygulama en az 300 bin küçülmektedir.
  • genel alt sınıfları NSObjectiçin destek; daha fazla bilgi için bkz . NSObject Generics . Ayrıca yeni kayıt sistemi, daha önce çalışma zamanında rastgele davranışa neden olabilecek desteklenmeyen genel yapıları yakalar.

Yeni tarafından yakalanan hatalar registrar

Aşağıda yeni registrartarafından yakalanan hatalara bazı örnekler 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ı Objective-C ada sahip birden fazla yönetilen sınıfı dışarı 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> () {}
    }
    

Yeni sürümün sınırlamaları registrar

Yeni registrarhakkında göz önünde bulundurulması gereken bazı şeyler:

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

  • Kısa vadeli bir dezavantaj da, Hesaplar çerçevesi kullanıldığında Clang'in kullanılması gerektiğidir (bunun nedeni Apple'ın accounts.h üst bilgisinin yalnızca Clang tarafından derlenebilir olmasıdır). Xcode 4.6 veya önceki bir sürümü kullanıyorsanız Clang kullanmak için ek mtouch bağımsız değişkenlerine ekleyin --compiler:clang (Xamarin.iOS, Xcode 5.0 veya sonraki sürümlerde Clang'yi otomatik olarak seçer.)

  • Xcode 4.6 (veya öncesi) kullanılıyorsa, dışarı aktarılan 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 koddaki Objective-C tanımlayıcıların içinde ASCII olmayan karakterleri desteklememesidir). GCC kullanmak için ek mtouch bağımsız değişkenlerine ekleyin --compiler:gcc .

Bir registrar

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

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

Not

Xamarin'in Klasik API'sinde ve --registrar:legacydynamicgibi --registrar:legacystatic diğer seçenekler desteklenir. Ancak, bu seçenekler Birleşik API tarafından desteklenmez.

Eski kayıt sistemindeki eksiklikler

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

  • Üçüncü taraf yerel kitaplıklarda sınıflara ve yöntemlere Objective-C (yerel) statik başvuru yoktu. Bu, yerel bağlayıcıdan aslında kullanılmayan üçüncü taraf yerel kodu kaldırmasını isteyemediğimiz anlamına geliyordu (çünkü her şey kaldırılacaktı). Bu, her üçüncü taraf bağlamasının -force_load libNative.a (veya özniteliğindeki eşdeğerin ForceLoad=true ) yapılması gereken nedenidir [LinkWith] .
  • Uyarı olmadan aynı Objective-C ada sahip iki yönetilen türü dışarı aktarabilirsiniz. Nadir bir senaryo, farklı ad alanlarına iki AppDelegate sınıf eklemekti. Çalışma zamanında hangisinin seçildiği tamamen rastgele olurdu (aslında, yeniden derlenmemiş bir uygulamanın çalıştırmaları arasında değişiklik gösterildi - bu da çok şaşırtıcı ve sinir bozucu bir hata ayıklama deneyimi için yapıldı).
  • Aynı Objective-C imzaya sahip iki yöntemi dışarı aktarabilirsiniz. Yine de hangisinden Objective-C çağrılacağı rastgeleydi (ancak bu sorun önceki kadar yaygın değildi, çünkü bu hatayı gerçekten yaşamanın tek yolu şanssız yönetilen yöntemi geçersiz kılmaktı).
  • Dışarı aktarılan yöntem kümesi, dinamik ve statik derlemeler arasında biraz farklıydı.
  • Genel sınıfları dışarı aktarırken düzgün çalışmaz (çalışma zamanında yürütülen tam genel uygulama rastgele olur ve etkili bir şekilde belirlenemeyen davranışa neden olur).

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

Bu bölümde, yeni registrarile çalışmak için yapılması gereken bağlama değişiklikleri açıklanmaktadır.

Protokoller [Protocol] özniteliğine sahip olmalıdır

Protokoller artık özniteliğine [Protocol] sahip olmalıdır. Bunu yapmazsanız, aşağıdakiler gibi yerel bir bağlayıcı hatası alırsınız:

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

Seçicilerin geçerli sayıda parametresi olmalıdır

Tüm seçiciler parametre sayısını doğru şekilde belirtmelidir. Daha önce bu hatalar yoksayıldı ve çalışma zamanı sorunlarına neden olabiliyordu.

Kısacası, iki nokta üst üste sayısı parametre sayısıyla eşleşmelidir:

  • 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şlevleri özniteliği için IsVariadic bağımsız değişkenini [Export] kullanmalıdır:

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

Yerel kitaplıkta var olmayan sınıfları bağlamak mümkün değildir. Yerel kitaplıktan bir sınıf kaldırıldıysa veya yeniden adlandırıldıysa, bağlamaları eşleşecek şekilde güncelleştirin.