Xamarin.iOS API Tasarımı

Mono'nın parçası olan temel Temel Sınıf Kitaplıklarına ek olarak Xamarin.iOS, geliştiricilerin Mono ile yerel iOS uygulamaları oluşturmasına olanak sağlayan çeşitli iOS API'leri için bağlamalarla birlikte sunar.

Xamarin.iOS'un çekirdeğinde, C# dünyayla dünya arasında köprüler ve Objective-C CoreGraphics ve OpenGL ES gibi iOS C tabanlı Objective-Ciçin bağlamalar bulunan bir birlikte çalışma altyapısı vardır.

Kodla iletişim kurmak için alt düzey çalışma Objective-C zamanı Objective-C Ayrıca Foundation,CoreFoundation ve UIKit bağlamaları da sağlanır.

Tasarım İlkeleri

Bu bölümde Xamarin.iOS bağlamalarına ilişkin tasarım ilkelerimizin bazıları ayrıntılı olarak ve ayrıntılı olarak ve ayrıca macOS'ta mono bağlamaları olan Xamarin.Mac için Objective-C de geçerlidir):

  • Çerçeve Tasarımı Yönergelerini Izleyin

  • Geliştiricilerin sınıfları alt sınıflara sınıflandırmasına izin Objective-C ver:

    • Mevcut bir sınıftan türet
    • Zincire temel oluşturucu çağırma
    • Geçersiz kılma yöntemleri C#'nin geçersiz kılma sistemiyle yapılmalı
    • Alt sınıf C# standart yapıları ile çalışmalı
  • Geliştiricileri seçicilere Objective-C açık yapma

  • Rastgele kitaplıkları çağıracak bir Objective-C mekanizma sağlama

  • Ortak görevleri Objective-C kolay ve sabit görevleri mümkün Objective-C yapma

  • Özellikleri Objective-C C# özellikleri olarak ortaya çıkarma

  • Kesin olarak türü kesin olarak türü kesin olan bir API'yi ortaya çıkarma:

    • Tür güvenliğini artırma
    • Çalışma zamanı hatalarını en aza indirme
    • Dönüş türlerinde IDE IntelliSense'i al
    • IDE açılır belgelerine izin verir
  • API'leri IDE içinde keşfetmeye teşvik etmek:

    • Örneğin, zayıf türe bir diziyi şu şekilde açığa çıkararak:

      NSArray *getViews
      

      Aşağıdaki gibi güçlü bir türü ortaya çıkarma:

      NSView [] Views { get; set; }
      

      Güçlü türlerin Mac için Visual Studio API'ye göz atarak otomatik tamamlama yapma olanağı sağlar, döndürülen değerde tüm işlemleri kullanılabilir yapar ve dönüş değerinin LINQ'a katılmasını System.Array sağlar.

  • Yerel C# türleri:

    • Olur string

    • Öznitelikleri intuint olan C# numaralarına ve C# numaralarına sahip olması gereken ve parametrelerini [Flags] dönüştür

    • Türünden bağımsız nesneler NSArray yerine, dizileri kesin olarak türü kesin olarak yazılmış diziler olarak ortaya çıkarır.

    • Olaylar ve bildirimler için kullanıcılara şunların arasında bir seçim yapın:

      • Varsayılan olarak kesin olarak türü kesin olarak yazıldı sürümü
      • Gelişmiş kullanım örnekleri için zayıf türe sahip bir sürüm
  • Temsilci Objective-C desenini destekle:

    • C# olay sistemi
    • C# temsilcilerini (lambdalar, anonim yöntemler ve ) API'lere System.Delegate blok olarak Objective-C maruz

Bütünleştirilmiş Kodlar

Xamarin.iOS, Xamarin.iOSProfilini oluşturan birçok derleme içerir. Derlemeler sayfası daha fazla bilgi içerir.

Ana Ad Alanları

ObjCRuntime

ObjCRuntime ad alanı, geliştiricilerin C# ile arasındaki dünyalar arasında köprüye sahip olduğunu sağlar. Bu, Cocoa# ve Gtk# deneyimlerine göre iOS için özel olarak tasarlanmış yeni bir bağlamadır.

Temel

Foundation ad alanı, iOS'un bir parçası olan Foundation çerçevesiyle birlikte çalışabilmek için tasarlanmış temel veri türlerini sağlar ve içinde nesne odaklı programlamanın temelini Objective-C oluşturur.

C# içinde Xamarin.iOS yansıtmaları sınıf hiyerarşisi from Objective-C . Örneğin, temel Objective-C NSObject sınıfı Objective-Caracılığıyla C# ile kullanılabilir.

Foundation ad alanı temel alınan Foundation türleri için bağlamalar sağlar ancak birkaç durumda temel alınan türleri Objective-C .NET türleriyle eşlemektedir. Örnek:

  • Çalışma zamanı, NSString ve NSArrayile ilgilenmek yerine bunları C#dizeleri ve kesin olarak türü kesin olarak yazıldı dizileriolarak API'de gösterir.

  • Geliştiricilerin şu anda Xamarin.iOS tarafından bağlı olmayan üçüncü taraf API'leri, diğer iOS API'leri veya API'leri bağlamasına olanak sağlayan çeşitli yardımcı API'ler Objective-C burada açıklanacak.

BAĞLAMA API'leri hakkında daha fazla bilgi için Xamarin.iOS Bağlama Oluşturucu bölümüne bakın.

NSObject

NSObject türü tüm bağlamaların temelini alır. Xamarin.iOS türleri iOS CocoaTouch API'lerinden iki tür sınıfını yansıtır: C türleri (genellikle CoreFoundation türleri olarak adlandırılır) ve türleri (bunların hepsi NSObject sınıfından Objective-C türetilen).

Bir unmanaged türünü yansıtan her tür için, Handle özelliği aracılığıyla yerel nesneyi almak mümkündür.

Mono tüm nesneleriniz için atık toplama sağlar ancak Foundation.NSObjectFoundation.NSObject kullanır. Atık Toplayıcı'nın devreye girmeden herhangi bir NSObject'in kaynaklarını açıkça serbest ebilirsiniz. Büyük veri bloklarının işaretçilerini tutan UIImage'lar gibi ağır NSObjects kullanırken kaynakları açıkça serbest bırakmak önemlidir.

Türün belirlenimci sonlaştırma gerçekleştirmesi gerekirse, NSObject.Dispose(bool) yöntemini geçersiz kılın Dispose parametresi "bool disposeosing" olur ve true olarak ayarlanırsa, kullanıcı nesnede Dispose () açıkça çağırması nedeniyle Dispose yönteminizin çağrılması anlamına gelir. False değeri, dispose(bool disposing) yönteminizin sonlandırıcı iş parçacığında sonlandırıcıdan çağrıldı anlamına gelir.

Kategoriler

Xamarin.iOS 8.10'dan başlayarak Objective-C C# ile kategori oluşturmak mümkündür.

Bu, özniteliğine Category bağımsız değişken olarak genişletilen türü belirterek özniteliği kullanılarak yapılır. Aşağıdaki örnek NSString'i genişletecek.

[Category (typeof (NSString))]

Her kategori yöntemi, yöntemleri özniteliğini kullanarak dışarı aktarmaya yönelik normal Objective-C mekanizmayı Export kullanır:

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

Tüm yönetilen uzantı yöntemleri statik olmalıdır, ancak C# içinde uzantı yöntemleri için standart söz dizimi kullanarak Objective-C örnek yöntemleri oluşturmak 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öntemin çağrıldığında kullanılan örnek olur.

Tamamlanan örnek:

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

Bu örnek, NSString sınıfına yerel bir toUpper örnek yöntemi ekler ve bu yöntemden Objective-C çağrılabilir.

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

Bunun yararlı olduğu senaryolardan biri, kod tabanınız içinde bir sınıf kümesine yöntem eklemektir. Örneğin bu, tüm örneklerin UIViewController döndürebilirlerini rapor etmelerini sağlar:

[Category (typeof (UINavigationController))]
class Rotation_IOS6 {
      [Export ("shouldAutorotate:")]
      static bool ShouldAutoRotate (this UINavigationController self)
      {
          return true;
      }
}
PreserveAttribute

PreserveAttribute, uygulamanın boyutunu azaltmak için işlenme aşamasında bir türü veya türün üyesini korumak için Mtouch'a (Xamarin.iOS dağıtım aracı) söylemek için kullanılan özel bir özniteliktir.

Uygulama tarafından statik olarak bağlantılı olmayan her üye kaldırılabilir. Bu nedenle, bu öznitelik statik olarak başvurulmasa da, yine de uygulamanıza gereken üyeleri işaretlemek için kullanılır.

Örneğin, türleri dinamik olarak örneği oluşturursanız, türlerinizi varsayılan oluşturucusu korumak istiyor olabilir. XML serileştirme kullanıyorsanız, türlerinizin özelliklerini korumak istiyor olabilir.

Bu özniteliği bir türün her üyesine veya türün kendisine uygulayabilirsiniz. Türün tamamını korumak için tür üzerinde [Koru (AllMembers = true)] söz dizimlerini kullanabilirsiniz.

UIKit

UIKit ad alanı, C# sınıfları şeklinde CocoaTouch'u tüm kullanıcı arabirimi bileşenlerine bire bir eşleme içerir. API, C# dilinde kullanılan kuralları takip edecek şekilde değiştirilmiştir.

Yaygın işlemler için C# temsilcileri sağlanır. Daha fazla bilgi için temsilciler bölümüne bakın.

OpenGLES

OpenGLES için nesne odaklı bir bağlama olan OpenTK API'nin değiştirilmiş sürümünü CoreGraphics veri türlerini ve yapılarını kullanmak üzere değiştirilmiş ve yalnızca iOS'ta kullanılabilir olan işlevselliği açığa çıkararak OpenGL'ye dağıtacağız.

OpenGLES 1.1 işlevselliği, ES11.GL kullanılabilir.

OpenGLES 2.0 işlevselliği, ES20.GL kullanılabilir.

OpenGLES 3.0 işlevselliği, ES30.GL kullanılabilir.

Bağlama Tasarımı

Xamarin.iOS yalnızca temel alınan platforma bir bağlama Objective-C değildir. .NET tür sistemini genişleten bu sistem, C# ve ile arasında daha iyi bir uyum Objective-C sağlar.

P/Invoke'un Windows ve Linux üzerinde yerel kitaplıkları çağırmak için kullanışlı bir araç olduğu gibi veya IJW desteği Windows'de COM birlikte çalışma için kullanılasa da Xamarin.iOS, C# nesnelerini nesnelere bağlamayı desteklemek için çalışma zamanının süresini Objective-C genişletmektedir.

Sonraki birkaç bölümde yer alan tartışma, Xamarin.iOS uygulamaları oluşturmakta olan kullanıcılar için gerekli değildir, ancak geliştiricilerin işleri nasıl tamamlasa da daha karmaşık uygulamalar oluştururken onlara yardımcı olur.

Türler

Mantıklı olan, C# türleri C# evreni için alt düzey Temel türleri yerine ortaya çıkar. Bu, API'nin NSString yerine C# "string" türünü kullandığı ve NSArray'yi açığa çıkararak yerine kesin olarak türü kesin olarak yazıldı C# dizilerini kullandığı anlamına gelir.

Genel olarak, Xamarin.iOS ve Xamarin.Mac tasarımında temel NSArray alınan nesne açığa çıkarlanmaz. Bunun yerine, çalışma zamanı, NSArray s 'yi bir sınıfın kesin türü belirlenmiş dizilerine otomatik olarak dönüştürür NSObject . Bu nedenle, Xamarin. iOS bir NSArray döndürmek için GetViews gibi zayıf türsüz bir yöntem sunmaz:

NSArray GetViews ();

Bunun yerine, bağlama kesin türü belirtilmiş bir dönüş değeri gösterir, örneğin:

UIView [] GetViews ();

NSArrayDoğrudan kullanmak isteyebileceğiniz köşe durumları için, içinde sunulan birkaç yöntem vardır NSArray , ancak API bağlamasında kullanımları önerilmez.

Ayrıca, CoreGraphics API 'sini göstermek yerine Classic API , ve CGPointCGSizeSystem.DrawingRectangleFPointFSizeF geliştiricilerin opentk kullanan mevcut OpenGL kodlarını korumalarına yardımcı olacak şekilde, ve uygulamaları ile değiştirdik. Yeni 64 bit Unified APIkullanılırken COREGRAPHICS API 'sinin kullanılması gerekir.

Devralma

Xamarin. iOS API tasarımı, geliştiricilerin yerel Objective-C türleri bir C# türünü genişletecek şekilde genişletmelerine, türetilmiş bir sınıfta "override" anahtar sözcüğünü kullanarak ve "Base" C# anahtar sözcüğünü kullanarak temel uygulamaya zincirlemeye olanak tanır.

Bu tasarım Objective-C , tüm Objective-C sistemin Xamarin. iOS kitaplıklarında zaten sarmalanmış olması nedeniyle geliştiricilerin, geliştirme sürecinin bir parçası olarak seçicilerle uğraşmasını önlamalarını sağlar.

Türler ve Interface Builder

Interface Builder tarafından oluşturulan türlerin örnekleri olan .NET sınıfları oluşturduğunuzda, tek bir parametre alan bir Oluşturucu sağlamanız gerekir IntPtr . Yönetilen nesne örneğini yönetilmeyen nesneyle bağlamak için bu gereklidir. Kod, şöyle tek bir satırdan oluşur:

public partial class void MyView : UIView {
   // This is the constructor that you need to add.
   public MyView (IntPtr handle) : base (handle) {}
}

Temsilciler

Objective-C ve C# ' nin her dildeki sözcük temsilcisinin farklı anlamları vardır.

Objective-CDünyada ve CocoaTouch hakkında çevrimiçi olarak bulacağınız belgelerde, bir temsilci genellikle bir yöntem kümesine yanıt verecek bir sınıfın örneğidir. Bu, yöntemlerin her zaman zorunlu olmaması bakımından bir C# arabirimine benzerdir.

Bu temsilciler, Uııkit ve diğer CocoaTouch API 'Lerinde önemli bir rol oynar. Bunlar çeşitli görevleri gerçekleştirmek için kullanılır:

  • Kodunuza bildirim sağlamak için (C# veya GTK + ile olay teslimine benzer).
  • Veri görselleştirme denetimlerine yönelik modeller uygulamak için.
  • Bir denetimin davranışını denetlemek için.

Programlama stili, bir denetimin davranışını değiştirecek türetilmiş sınıfların oluşturulmasını en aza indirmek için tasarlanmıştır. Bu çözüm, şu yıllar için diğer GUI araç setlerinin ne kadar yapıldığına yönelik olduğuna benzer: GTK 'nin sinyalleri, QT yuvaları, WinForms olayları, WPF/Silverlight olayları vb. Yüzlerce arabirime sahip olmaktan kaçınmak için (her bir eylem için) veya geliştiricilerin gerek duyulmayan çok fazla yöntem uygulaması gerektirmesi için Objective-C isteğe bağlı yöntem tanımlarını destekler. Bu, tüm yöntemlerin uygulanması gereken C# arabirimlerinden farklıdır.

Objective-CSınıflarda, bu programlama deseninin kullanıldığı sınıfların bir özelliği kullanıma sunduğundan delegate ve isteğe bağlı bölümlerin, sıfır ya da daha fazlasını yapmak için gereken adlı bir özellik olduğunu görürsünüz.

Xamarin. iOS içinde bu temsilcilere bağlamak için birbirini dışlayan üç mekanizma sunulmaktadır:

  1. Olaylar aracılığıyla.
  2. Bir özellik aracılığıyla kesin tür
  3. Bir özellik ile gevşek olarak yazılmış

Örneğin, UIWebView sınıfını düşünün. Bu, Delegate özelliğine atanan bir UIWebViewDelegate örneğine dağıtır.

Olaylar aracılığıyla

Birçok tür için, Xamarin. iOS otomatik olarak uygun bir temsilci oluşturur ve bu da UIWebViewDelegate çağrıları C# olaylarına iletir. UIWebView için:

Örneğin, bu basit program bir Web görünümü yüklerken başlangıç ve bitiş zamanlarını kaydeder:

DateTime startTime, endTime;
var web = new UIWebView (new CGRect (0, 0, 200, 200));
web.LoadStarted += (o, e) => startTime = DateTime.Now;
web.LoadFinished += (o, e) => endTime = DateTime.Now;
Özellikler aracılığıyla

Olaylar, olaya birden fazla abone olabileceği zaman yararlıdır. Ayrıca, olaylar koddan bir dönüş değeri olmadığı durumlar ile sınırlıdır.

Kodun bir değer döndürmesi beklenen durumlarda özellikler için bunun yerine tercih ederiz. Bu, bir nesnede belirli bir zamanda yalnızca bir yöntemin ayarlanmayacağı anlamına gelir.

Örneğin, bu mekanizmayı, bir için işleyicisindeki ekranda Klavyeyi kapatmak için kullanabilirsiniz UITextField :

void SetupTextField (UITextField tf)
{
    tf.ShouldReturn = delegate (textfield) {
        textfield.ResignFirstResponder ();
        return true;
    }
}

UITextFieldShouldReturn Bu örnekte, bir bool değeri döndüren bir temsilci bağımsız değişkeni olarak ve TextField 'ın basıldığında Return düğmesiyle bir şey yapıp yapamayacağını belirleyen özelliği. Bu yöntemde, çağırana doğru döndürüyoruz, ancak klavyeyi ekrandan de kaldırdık (Bu, TextField çağırdığında olur ).

Temsilci özelliği aracılığıyla kesin tür

Olayları kullanmayı tercih ediyorsanız, kendi UIWebViewDelegate alt sınıfına girip UIWebView. Delegate özelliğine atayabilirsiniz. UIWebView. Delegate atandıktan sonra, UIWebView olay dağıtma mekanizması artık çalışmaz ve ilgili olaylar gerçekleştiğinde UIWebViewDelegate yöntemleri çağrılır.

Örneğin, bu basit tür bir Web görünümü yüklemek için geçen süreyi kaydeder:

class Notifier : UIWebViewDelegate  {
    DateTime startTime, endTime;

    public override LoadStarted (UIWebView webview)
    {
        startTime = DateTime.Now;
    }

    public override LoadingFinished (UIWebView webView)
    {
        endTime= DateTime.Now;
    }
}

Yukarıdaki kod aşağıdaki gibi kodda kullanılır:

var web = new UIWebView (new CGRect (0, 0, 200, 200));
web.Delegate = new Notifier ();

Yukarıdaki bir Uıwebviewer oluşturacak ve iletileri yanıtlamak için oluşturduğumuz bir sınıf olan bir bildirim örneğine ileti göndermesini ister.

Bu model, bazı denetimlerin davranışını denetlemek için de kullanılır (örneğin, UIWebView örneğinde, UIWebView. ShouldStartLoad özelliği, örneğin UIWebView bir sayfa yükleyip yükleyemeyeceğini denetlemesine olanak tanır.

Bu model, verileri birkaç denetim için isteğe bağlı olarak sağlamak için de kullanılır. Örneğin, UITableView denetimi güçlü bir tablo işleme denetimidir ve hem görünüm hem de Içerik bir Uıtableviewdatasource örneği tarafından yönlendiriliyor

WeakDelegate özelliği aracılığıyla gevşek olarak yazılmış

Türü kesin belirlenmiş olan özelliğe ek olarak, Ayrıca, geliştiricilerin istenirse farklı şekilde bağlamasını sağlayan zayıf tür bir temsilci vardır. Türü kesin belirlenmiş bir Delegate özelliğin her yerde Xamarin. iOS bağlamasında, buna karşılık gelen bir WeakDelegate özellik de sunulur.

Kullanırken WeakDelegate , seçiciyi belirtmek Için WeakDelegate özniteliğini kullanarak sınıfınızı doğru bir şekilde dekorasyon siz sorumlusunuz. Örnek:

class Notifier : NSObject  {
    DateTime startTime, endTime;

    [Export ("webViewDidStartLoad:")]
    public void LoadStarted (UIWebView webview)
    {
        startTime = DateTime.Now;
    }

    [Export ("webViewDidFinishLoad:")]
    public void LoadingFinished (UIWebView webView)
    {
        endTime= DateTime.Now;
    }
}

[...]

var web = new UIWebView (new CGRect (0, 0, 200, 200));
web.WeakDelegate = new Notifier ();

WeakDelegateÖzellik atandıktan sonra, Delegate özelliği kullanılmaz. Ayrıca, yöntemi [dışarı aktarma] yapmak istediğiniz devralınmış bir temel sınıfta uygularsanız, bunu ortak bir yöntem yapmanız gerekir.

Objective-CTemsilci deseninin C 'ye eşlenmesi #

Objective-CŞöyle görünen örnekler gördüğünüzde:

foo.delegate = [[SomethingDelegate] alloc] init]

Bu, dile "SomethingDelegate" sınıfının bir örneğini oluşturup oluşturmasını ve değeri foo değişkeninde Delegate özelliğine atamayı söyler. Bu mekanizma, Xamarin. iOS ve C# tarafından desteklenir, sözdizimi şöyledir:

foo.Delegate = new SomethingDelegate ();

Xamarin. iOS içinde, temsilci sınıflarıyla eşlenen türü kesin belirlenmiş sınıflar sağladık Objective-C . Bunları kullanmak için altsınıflama olur ve Xamarin. iOS uygulamasının uygulama tarafından tanımlanan yöntemleri geçersiz kılarsınız. Nasıl çalıştıkları hakkında daha fazla bilgi için aşağıdaki "modeller" bölümüne bakın.

Temsilcileri C 'ye eşleme #

Genel olarak, Objective-C iki formdaki temsilciler kullanır.

İlk form, bir bileşenin modeline arabirim sağlar. Örneğin, bir liste görünümü için veri depolama olanağı gibi bir görünüm için isteğe bağlı veri sağlama mekanizması olarak. Bu durumlarda, her zaman uygun sınıfın bir örneğini oluşturmanız ve değişkeni atamanız gerekir.

Aşağıdaki örnekte, UIPickerView dizesini kullanan bir model için bir uygulama sağlar:

public class SampleTitleModel : UIPickerViewTitleModel {

    public override string TitleForRow (UIPickerView picker, nint row, nint component)
    {
        return String.Format ("At {0} {1}", row, component);
    }
}

[...]

pickerView.Model = new MyPickerModel ();

İkinci form, olaylar için bildirim sağlamaktır. Bu gibi durumlarda, API 'yi yukarıda belirtilen biçimde kullanıma sunduk, ancak hızlı işlemler için kullanılması ve c# ' deki anonim temsilcilerle ve lambda ifadeleriyle tümleştirilmesine yönelik daha basit olması gereken C# olaylarını da sunuyoruz.

Örneğin, olaylara abone olabilirsiniz UIAccelerometer :

UIAccelerometer.SharedAccelerometer.Acceleration += (sender, args) => {
   UIAcceleration acc = args.Acceleration;
   Console.WriteLine ("Time={0} at {1},{2},{3}", acc.Time, acc.X, acc.Y, acc.Z);
}

İki seçenek de anlamlı oldukları yerlerde mevcuttur, ancak bir programcı olarak bir veya diğerini seçmeniz gerekir. Türü kesin belirlenmiş bir Yanıtlayıcının kendi örneğini oluşturursanız ve atarsanız, C# olayları işlevsel olmayacaktır. C# olaylarını kullanırsanız, Yanıtlayıcı/temsilci sınıfınıza ilişkin yöntemler hiçbir şekilde çağrılmaz.

Kullanılan önceki örnek UIWebView Şu şekilde C# 3,0 Lambdalar kullanılarak yazılabilir:

var web = new UIWebView (new CGRect (0, 0, 200, 200));
web.LoadStarted += () => { startTime = DateTime.Now; }
web.LoadFinished += () => { endTime = DateTime.Now; }

Olaylara yanıt verme

Kodda, bazen birden fazla denetim için Objective-C olay işleyicileri ve birden çok denetim için bilgi sağlayıcıları aynı sınıfta barındırılır. Bu, sınıfların iletilere yanıt verdiği ve sınıfların iletilere yanıt verdiği sürece nesneleri birbirine bağlamak mümkündür.

Daha önce açıklandığı gibi, Xamarin. iOS hem C# olay tabanlı programlama modelini hem de Objective-C temsilciyi uygulayan yeni bir sınıf oluşturabileceğiniz ve istenen yöntemleri geçersiz kılabileceğiniz temsilci modelini destekler.

Objective-CAynı zamanda birden çok farklı işlem için Yanıtlayıcılar bir sınıfın aynı örneğinde barındırıldığından, desteklemek de mümkündür. Bunu yapmak için, Xamarin. iOS bağlamasının alt düzey özelliklerini kullanmanız gerekecektir.

Örneğin, sınıfınızın hem UITextFieldDelegate.textFieldShouldClear : Message hem de UIWebViewDelegate.webViewDidStartLoad : sınıfının aynı örneğinde yanıt vermesini istediyseniz, [Export] öznitelik bildirimini kullanmanız gerekir:

public class MyCallbacks : NSObject {
    [Export ("textFieldShouldClear:"]
    public bool should_we_clear (UITextField tf)
    {
        return true;
    }

    [Export ("webViewDidStartLoad:")]
    public void OnWebViewStart (UIWebView view)
    {
        Console.WriteLine ("Loading started");
    }
}

Yöntemlerin C# adları önemli değildir; her önemli şey [Export] özniteliğine geçirilen dizelerdir.

Bu programlama stilini kullanırken, C# parametrelerinin, çalışma zamanı altyapısının geçitide olacağı gerçek türlerle eşleştiğinden emin olun.

Modeller

Uııt Storage tesislerinde veya yardımcı sınıflar kullanılarak uygulanan Yanıtlayıcılar içinde, bunlar Objective-C kodda temsilciler olarak başvurulur ve protokol olarak uygulanır.

Objective-C protokoller arabirimler gibidir, ancak isteğe bağlı yöntemleri destekler; diğer bir deyişle, protokolün çalışması için tüm yöntemlerin uygulanması gerekmez.

Bir modeli kullanmanın iki yolu vardır. Bunu el ile uygulayabilir ya da kesin türü belirtilmiş tanımları kullanabilirsiniz.

Xamarin. iOS tarafından bağlanmayan bir sınıfı uygulamaya çalıştığınızda el ile mekanizma gereklidir. Kolayca yapılacak:

  • Çalışma zamanı ile kayıt için sınıfınıza bayrak uygulama
  • Geçersiz kılmak istediğiniz her yönteme gerçek seçici adıyla [Export] özniteliğini uygulama
  • sınıfının örneğini ve ardından bunu iletin.

Örneğin, aşağıdakiler UIApplicationDelegate protokol tanımında isteğe bağlı yöntemlerden yalnızca birini uygulamaya almaktadır:

public class MyAppController : NSObject {
        [Export ("applicationDidFinishLaunching:")]
        public void FinishedLaunching (UIApplication app)
        {
                SetupWindow ();
        }
}

Seçici Objective-C adı ("applicationDidFinishLaunching:") Export özniteliğiyle bildirildi ve sınıfı özniteliğiyle [Register] kaydedildi.

Xamarin.iOS, el ile bağlama gerektirmeyen, kullanıma hazır, kesin olarak türü kesin olarak yazıldı bildirimleri sağlar. Bu programlama modelini desteklemek için Xamarin.iOS çalışma zamanı bir sınıf bildirimi üzerinde [Model] özniteliğini destekler. Bu, yöntemler açıkça uygulanmadıkça çalışma zamanını sınıftaki tüm yöntemlerin kablolarını çekmesi gerektiğini belirtir.

Bu, UIKit'te isteğe bağlı yöntemlerle bir protokolü temsil eden sınıfların şu şekilde yazıldığı anlamına gelir:

[Model]
public class SomeViewModel : NSObject {
    [Export ("someMethod:")]
    public virtual int SomeMethod (TheView view) {
       throw new ModelNotImplementedException ();
    }
    ...
}

Yalnızca bazı yöntemleri uygulayan bir model uygulamak istediğiniz zaman, tek gereken ilgilendiğiniz yöntemleri geçersiz kılmak ve diğer yöntemleri yoksaymaktır. Çalışma zamanı dünyaya özgün yöntemleri değil yalnızca üzerine yazılan yöntemleri Objective-C bağlayacaktır.

Önceki el ile yapılan örneğin eşdeğeri şu şekildedir:

public class AppController : UIApplicationDelegate {
    public override void FinishedLaunching (UIApplication uia)
    {
     ...
    }
}

Bunun avantajları seçiciyi, bağımsız değişkenlerin türlerini veya C# ile eşlemeyi bulmak için üst bilgi dosyalarını incelemenin gerekmesi ve güçlü türlerle birlikte Mac için Visual Studio'den IntelliSense elde etmektir Objective-C

XIB Çıkışları ve C #

Bu, Çıkışların C# ile nasıl tümleştirildiklerinin alt düzey bir açıklamasıdır ve Xamarin.iOS'un ileri düzey kullanıcıları için sağlanır. Bu Mac için Visual Studio, sizin için uçuşta oluşturulan kod kullanılarak arka uçta otomatik olarak yapılır.

Interface Builder ile kullanıcı arabiriminizi tasarlarken yalnızca uygulamanın görünümlerini tasarlar ve bazı varsayılan bağlantılar kurabilirsiniz. Bilgileri program aracılığıyla getirmek, çalışma zamanında denetimin davranışını değiştirmek veya denetimi çalışma zamanında değiştirmek için, bazı denetimleri yönetilen kodunuzla bağlamak gerekir.

Bu birkaç adımda yapılır:

  1. Çıkış bildirimini Dosyanınsahibine ekleyin.
  2. Bağlan dosyanın sahibine kaydedin.
  3. Kullanıcı arabirimini ve bağlantıları XIB/NIB dosyanıza depolar.
  4. NIB dosyasını çalışma zamanında yükleme.
  5. Çıkış değişkenine erişin.

Bu adımlar (1) ile (3) Apple'ın uygulama ve uygulama arabirimleri Interface Builder.

Xamarin.iOS kullanırken, uygulamanın UIViewController'dan türetilen bir sınıf oluşturması gerekir. Şu şekilde uygulanır:

public class MyViewController : UIViewController {
    public MyViewController (string nibName, NSBundle bundle) : base (nibName, bundle)
    {
        // You can have as many arguments as you want, but you need to call
        // the base constructor with the provided nibName and bundle.
    }
}

Ardından ViewController'ını bir NIB dosyasından yüklemek için şunları yapar:

var controller = new MyViewController ("HelloWorld", NSBundle.MainBundle, this);

Bu, NIB'den kullanıcı arabirimini yükler. Şimdi, çıkışlara erişmek için çalışma zamanının onlara erişmek istediğinize bildirmesi gerekir. Bunu yapmak için alt UIViewController sınıfların özellikleri bildir ihtiyaçları vardır ve [Bağlan] özniteliğiyle açıklama ek açıklamalarını içerir. Böyle:

[Connect]
UITextField UserName {
    get {
        return (UITextField) GetNativeField ("UserName");
    }
    set {
        SetNativeField ("UserName", value);
    }
}

Özellik uygulaması, gerçek yerel türün değerini gerçekten getirir ve depolar.

Mac için Visual Studio ve InterfaceBuilder kullanırken bu konuda endişelenmeniz gerek değildir. Mac için Visual Studio, bildirilen tüm çıkışları projenizin parçası olarak derlenmiş kısmi bir sınıfta kodla otomatik olarak yansıtıyor.

Seçiciler

Programlamanın temel Objective-C kavramlardan biri seçicilerdir. Genellikle bir seçiciyi geçmenizi gerektiren veya kodunuzun bir seçiciye yanıt vermelerini beklediğiniz API'ler ile karşı karşıya gelirsiniz.

C# içinde yeni seçiciler oluşturmak kolaydır; yalnızca sınıfının yeni bir örneğini oluşturur ve sonucu API'de bunu gerektiren herhangi bir ObjCRuntime.Selector yerde kullanırsınız. Örnek:

var selector_add = new Selector ("add:plus:");

Bir seçici çağrısına yanıt veren bir C# yöntemi için türünden devralması ve C# yönteminin özniteliği kullanılarak seçici adıyla birlikte dekore NSObject edilmiş olması [Export] gerekir. Örnek:

public class MyMath : NSObject {
    [Export ("add:plus:")]
    int Add (int first, int second)
    {
         return first + second;
    }
}

Seçici adları, varsa tüm ara ve sonda iki nokta üst üste (":") dahil olmak üzere tam olarak eşleşmeli.

NSObject Oluşturucuları

Xamarin.iOS'ta türetilen çoğu sınıf nesnenin işlevselliğine özgü oluşturucuları gösterir, ancak hemen belirgin olan çeşitli NSObject oluşturucuları da gösterir.

Oluşturucular aşağıdaki gibi kullanılır:

public Foo (IntPtr handle)

Bu oluşturucu, çalışma zamanının sınıfını bir unmanaged sınıfına eşlemesi gereken sınıfını örneği için kullanılır. Bu, bir XIB/NIB dosyası yükley000000000000000000000000000000 Bu noktada çalışma zamanı yönetilemeyen dünyada bir nesne oluşturur ve yönetilen tarafı başlatmak için bu oluşturucu Objective-C çağrılır.

Genellikle, tek gereken tanıtıcı parametresiyle temel oluşturucuya çağrı yapmak ve gövdede gerekli başlatmaları yapmaktır.

public Foo ()

Bu, bir sınıf için varsayılan oluşturucudur ve Xamarin.iOS tarafından sağlanan sınıflarda Foundation.NSObject sınıfını ve ile sonundaki tüm sınıfları başlatarak bunu sınıfındaki yöntemine Objective-Cinit zincirler.

public Foo (NSObjectFlag x)

Bu oluşturucu örneği başlatmak için kullanılır, ancak kodun sonunda Objective-C "init" yöntemini çağırması önlenebilir. Bunu genellikle başlatma için zaten kaydettiyken (oluşturucuda kullanıyorken) veya başlatmanızı başka bir ortalama aracılığıyla zaten [Export] yaptıyken kullanırsiniz.

public Foo (NSCoder coder)

Bu oluşturucu, nesnenin NSCoding örneğinden başlatılmış olduğu durumlar için sağlanır.

Özel durumlar

Xamarin.iOS API tasarımı, özel durumları Objective-C C# özel durumları olarak yükseltmez. Tasarım, dünyaya ilk olarak hiçbir çöp gönderilmez ve geçersiz veriler dünyaya geçirilmeden önce üretilecek özel durumların bağlama tarafından üretilmalarını Objective-CObjective-C zorunlu hale gelir.

Bildirimler

Hem iOS hem de OS X'te geliştiriciler, temel alınan platform tarafından yayınlanan bildirimlere abone olabilir. Bu, yöntemi kullanılarak NSNotificationCenter.DefaultCenter.AddObserver yapılır. yöntemi iki parametre alır; biri abone olmak istediğiniz bildirimdir, diğeri bildirim çağrıldığında AddObserver çağrılan yöntemdir.

Hem Xamarin.iOS hem de Xamarin.Mac'te, çeşitli bildirimlerin anahtarları bildirimleri tetikleyen sınıfta barındırıldı. Örneğin, tarafından uzan bildirimler, sınıflarda "Notification" adıyla sona eren özellikler UIMenuControllerstatic NSString olarak UIMenuController barındırıldı.

Bellek Yönetimi

Xamarin.iOS,artık kullanımda olmadığı zaman kaynakları sizin için serbest bırakmayla ilgilenecek bir atık toplayıcıya sahip. Atık toplayıcıya ek olarak, arabiriminden türetilen NSObject tüm System.IDisposable nesneler.

NSObject ve IDisposable

Arabirimin açığa çıkar bırakılması, geliştiricilerin büyük bellek bloklarını kapsülleyebiliyor nesneleri serbest bırakmasına yardımcı olmak için kullanışlı bir yoldur (örneğin, bir işaretçi gibi görünür, ancak 2 megabaytlık bir görüntüye işaret ediyor olabilir) ve diğer önemli ve sonlu kaynaklar (video kodunu çözme arabelleği IDisposableUIImage gibi).

NSObject, IDisposable arabirimini ve ayrıca .NET Dispose desenini uygular. Bu, NSObject alt sınıf geliştiricilerin Dispose davranışını geçersiz kılması ve isteğe bağlı olarak kendi kaynaklarını serbest bırakmalarına olanak sağlar. Örneğin, bir grup görüntü etrafında tutan bu görünüm denetleyicisini düşünün:

class MenuViewController : UIViewController {
    UIImage breakfast, lunch, dinner;
    [...]
    public override void Dispose (bool disposing)
    {
        if (disposing){
             if (breakfast != null) breakfast.Dispose (); breakfast = null;
             if (lunch != null) lunch.Dispose (); lunch = null;
             if (dinner != null) dinner.Dispose (); dinner = null;
        }
        base.Dispose (disposing)
    }
}

Yönetilen bir nesne atılması artık kullanışlı olmaz. Nesnelere hala başvurabilirsiniz, ancak nesnesi tüm amaçlara yöneliktir ve bu noktada geçersizdir. Bazı .NET API'leri, at alınan bir nesnede herhangi bir yönteme erişmeyi denersanız bunu bir ObjectDisposedException atarak sağlar, örneğin:

var image = UIImage.FromFile ("demo.png");
image.Dispose ();
image.XXX = false;  // this at this point is an invalid operation

"Image" değişkenine erişmeye devam ediyorsanız bile, bu gerçekten geçersiz bir başvuru olup artık görüntüyü Objective-C bulunduran nesneye yol göstermeyecektir.

Ancak bir nesneyi C# içinde elden etmek, nesnenin mutlaka yok edilecek olduğu anlamına gelmez. Tek yapacak şey, C# tarafından nesneye yapılan başvuru serbest bırakmaktır. Cocoa ortamı kendi kullanımı için bir başvurunun etrafında tutulmalıdır. Örneğin, bir UIImageView'un Image özelliğini bir görüntüye ayarlıyorsanız ve görüntüyü atsanız, temel alınan UIImageView kendi başvurularını almış ve kullanımı tamamlanıncaya kadar bu nesneye bir başvuru tutmaktadır.

Dispose ne zaman çağrılır?

Nesnenizi kurtulmak için Mono'ya ihtiyacınız olduğunda Dispose çağrısı. Olası kullanım örneklerinden biri, Mono'nın NSObject nesnenizin bellek veya bilgi havuzu gibi önemli bir kaynağa başvuru tuttuğu konusunda bilgi sahibi olmasıdır. Böyle durumlarda, Mono'ya çöp toplama döngüsü gerçekleştirmeyi beklemek yerine, başvuruyı belleğe hemen serbest bırakmak için Dispose çağrısında bulundurmalısınız.

Dahili olarak, Mono C# dizelerinden NSStringbaşvuruları oluşturduğunda, atık toplayıcının yapmaları gereken iş miktarını azaltmak için bunları hemen atacak. Başa baş etmek için ne kadar az nesne kullanırsa GC o kadar hızlı çalışır.

Nesnelere Başvuruların Ne Zaman Tutması Gerekir?

Otomatik bellek yönetiminin sahip olduğu yan etkilerden biri, GC'nin kullanılmayan nesnelere başvurular olmayan nesnelerden kurtulacak olmasıdır. Bazen şaşırtıcı yan etkileri olabilir. Örneğin, üst düzey görünüm denetleyicinizi veya üst düzey pencerenizi tutmak için yerel bir değişken oluşturmanız ve sonra bunların arkanızda kaybolmasını sağlarsanız.

Statik veya örnek değişkenlerinize yönelik bir başvuru tutamazsanız Mono, nesneleriniz üzerinde Dispose() yöntemini hemen çağıracak ve başvurularını nesnesine serbest bırakacak. Bekleyen tek başvuru bu olabileceği için çalışma Objective-C zamanı nesneyi sizin için yok eder.