Objective-C Xamarin.iOS'ta seçiciler
Dil Objective-C seçicileri Objective-C Seçici, bir nesnesine veya sınıfına gönderilen bir iletidir. Xamarin.iOS, örnek seçicileri örnek yöntemleriyle, sınıf seçicileri ise statik yöntemlerle eşler.
Normal C işlevlerinin (ve C++ üye işlevlerinin) aksine, P/Invoke Yerine kullanarak bir seçiciyi doğrudan çağıramazsanız, seçiciler kullanılarak bir sınıfa veya örneğine gönderilirobjc_msgSend Işlev.
'daki iletiler hakkında daha fazla Objective-C bilgi için Apple'ın Nesnelerle Objective-C atabilirsiniz.
Örnek
Şu çağrıyı yapmak istediğinizi varsayalım:sizeWithFont:forWidth:lineBreakMode: üzerinde NSString seçici.
Bildirim (Apple'ın belgelerinden) şöyledir:
- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode
Bu API aşağıdaki özelliklere sahiptir:
- Dönüş türü,
CGSizeUnified API. - parametresi
fontNSObject'dentüretilen birfont(ve türü (dolaylı olarak) ve System.IntPtr ile eşlenmiş. - parametresi
width,CGFloatilenfloateşlenmiş. - parametresi,
lineBreakModezatenUILineBreakModeXamarin.iOS'ta olarak bağlandıUILineBreakModeNumaralandırma.
Hepsini bir araya koyarak objc_msgSend bildiriminin eşleşmesi gerekir:
CGSize objc_msgSend(
IntPtr target,
IntPtr selector,
IntPtr font,
nfloat width,
UILineBreakMode mode
);
Bunu aşağıdaki gibi bildirebilirsiniz:
[DllImport (Constants.ObjectiveCLibrary, EntryPoint="objc_msgSend")]
static extern CGSize cgsize_objc_msgSend_IntPtr_float_int (
IntPtr target,
IntPtr selector,
IntPtr font,
nfloat width,
UILineBreakMode mode
);
Bu yöntemi çağırarak aşağıdaki gibi bir kod kullanın:
NSString target = ...
Selector selector = new Selector ("sizeWithFont:forWidth:lineBreakMode:");
UIFont font = ...
nfloat width = ...
UILineBreakMode mode = ...
CGSize size = cgsize_objc_msgSend_IntPtr_float_int(
target.Handle,
selector.Handle,
font == null ? IntPtr.Zero : font.Handle,
width,
mode
);
Döndürülen değer, boyutu 8 bayt'ın altında olan bir yapı olsaydı (Birleşik API'lere geçişten önce kullanılan eski kod gibi), yukarıdaki kod simülatörde çalıştırıldı ancak cihaz üzerinde SizeF kilitlenmeye başladı. Boyutu 8 bitten küçük bir değer döndüren bir seçiciyi çağırarak işlevini objc_msgSend_stret bildirin:
[DllImport (MonoTouch.Constants.ObjectiveCLibrary, EntryPoint="objc_msgSend_stret")]
static extern void cgsize_objc_msgSend_stret_IntPtr_float_int (
out CGSize retval,
IntPtr target,
IntPtr selector,
IntPtr font,
nfloat width,
UILineBreakMode mode
);
Bu yöntemi çağırarak aşağıdaki gibi bir kod kullanın:
NSString target = ...
Selector selector = new Selector ("sizeWithFont:forWidth:lineBreakMode:");
UIFont font = ...
nfloat width = ...
UILineBreakMode mode = ...
CGSize size;
if (Runtime.Arch == Arch.SIMULATOR)
size = cgsize_objc_msgSend_IntPtr_float_int(
target.Handle,
selector.Handle,
font == null ? IntPtr.Zero : font.Handle,
width,
mode
);
else
cgsize_objc_msgSend_stret_IntPtr_float_int(
out size,
target.Handle, selector.Handle,
font == null ? IntPtr.Zero: font.Handle,
width,
mode
);
Seçiciyi faturalama
Seçiciyi faturalamanın üç adımı var:
- Seçici hedefini al.
- Seçici adını al.
- Uygun
objc_msgSendbağımsız değişkenlerle çağrısı.
Seçici hedefleri
Seçici hedefi bir nesne örneği veya Objective-C sınıftır. Hedef bir örnekse ve bağlı bir Xamarin.iOS türünden gelmişse özelliğini ObjCRuntime.INativeObject.Handle kullanın.
Hedef bir sınıfsa sınıf ObjCRuntime.Class örneğine başvuru almak için kullanın ve ardından özelliğini Class.Handle kullanın.
Seçici adları
Seçici adları Apple'ın belgelerinde listelenir. Örneğin, NSString içerir sizeWithFont: ve sizeWithFont:forWidth:lineBreakMode: seçiciler. Ekli ve sonda iki nokta üst üste, seçici adının bir parçasıdır ve atlanamaz.
Seçici adınız olduktan sonra bunun için bir ObjCRuntime.Selector örnek oluşturabilirsiniz.
Objc_msgSend çağırma
objc_msgSend bir nesneye ileti (seçici) gönderir. Bu işlev ailesi en az iki gerekli bağımsız değişken alır: seçici hedefi (bir örnek veya sınıf tanıtıcısı), seçicinin kendisi ve seçici için gereken bağımsız değişkenler. Örnek ve seçici bağımsız değişkenleri, ve kalan tüm bağımsız değişkenler seçicinin beklediğiniz türle eşleşmesi gerekir; örneğin, bir için veya tüm türetilen türler için System.IntPtrnintintSystem.IntPtrNSObject bir. En üstteki USERNAME değerini kopyalamak için ekranın sağ tarafındakiNSObject.Handle bir tür örneği IntPtr için bir elde etmek için Objective-C özelliği.
Birden fazla işlev objc_msgSend vardır:
- Yapıyı
objc_msgSend_stretgeri alan seçiciler için kullanın. ARM'de bu, bir numaralama olmayan veya C yerleşik türlerinden herhangi biri olmayan tüm dönüş türlerini içerir (char, , , , ,shortintlongfloatdouble). x86'da (simülatör), bu yöntemin boyutu 8 bayt'ın üzerinde olan tüm yapılar için kullanılmalıdır (8 bayttır ve simülatördeCGSizeobjc_msgSend_stretkullanmaz). - Yalnızca
objc_msgSend_fpretx86 üzerinde kayan nokta değeri dönüşen seçiciler için kullanın. Bu işlevin ARM üzerinde kullanılmaya gerek yok; bunun yerineobjc_msgSendkullanın. - Ana objc_msgSend işlevi diğer tüm seçiciler için kullanılır.
Çağırmanız gereken işlev (simülatör ve cihaz için her biri farklı bir yönteme ihtiyaç olabilir) karar verdiktan sonra, işlevi daha sonra çağırma için bildiren normal bir objc_msgSend[DllImport] yöntem kullanabilirsiniz.
Önceden yapılmış bir bildirim objc_msgSend kümesi içinde ObjCRuntime.Messaging bulunabilir.
Simülatörde ve cihazda farklı çağrılar
Yukarıda açıklandığı gibi üç tür yöntem vardır: biri normal çağrılar, biri kayan nokta değerleri Objective-C (yalnızca x86) dönüşen çağrılar ve biri de yapı değerlerine dönüşen objc_msgSend çağrılar için. İkinci, içinde soneki _stretObjCRuntime.Messaging içerir.
Belirli yapılarını (aşağıda açıklanan kurallar) dönecek bir yöntemi çağırırsanız, ilk parametre olarak dönüş değerine sahip yöntemi bir değer olarak out çağırmalısiniz:
// The following returns a PointF structure:
PointF ret;
Messaging.PointF_objc_msgSend_stret_PointF_IntPtr (out ret, this.Handle, selConvertPointFromWindow.Handle, point, window.Handle);
yönteminin ne zaman kullanıla kuralı _stret_ x86 ve ARM'de farklılık gösterir.
Bağlamaların hem simülatörde hem de cihazda çalışması için aşağıdaki gibi bir kod ekleyin:
if (Runtime.Arch == Arch.DEVICE)
{
PointF ret;
Messaging.PointF_objc_msgSend_stret_PointF_IntPtr (out ret, myHandle, selector.Handle);
return ret;
}
else
{
return Messaging.PointF_objc_msgSend_PointF_IntPtr (myHandle, selector.Handle);
}
objc_msgSend_stret kullanma
ARM için hazırlarkenobjc_msgSend_stret bir numaralama veya bir numaralama için temel türlerden herhangi biri ( , , , , , ) için herhangi bir intbyte değer türü shortlongdoublefloat için.
x86 için hazırlarken kullanınobjc_msgSend_stret bir numaralama olmayan herhangi bir değer türü veya bir numaralama için temel türlerden herhangi biri için ( , , , , , ) ve yerel boyutu 8 bayttan intbyteshortlongdoublefloat büyüktür.
Kendi imzalarınızı oluşturma
Gerekirse, kendi imzalarınızı oluşturmak için aşağıdaki gist kullanılabilir.