Objective-C Xamarin.iOS'ta seçiciler
Dil Objective-C seçicileri temel alır. Seçici, bir nesneye veya sınıfa gönderilebilen bir iletidir. Xamarin.iOS , örnek seçicilerini örnek yöntemlerine, sınıf seçicileri ise statik yöntemlere eşler.
Normal C işlevlerinden (ve C++ üye işlevleri gibi) farklı olarak, bunun yerine P/Invoke kullanarak doğrudan bir seçici çağıramazsınız , seçiciler kullanılarak bir Objective-C sınıfa veya örneğe gönderilir objc_msgSend
Işlev.
içindeki Objective-Ciletiler hakkında daha fazla bilgi için Apple'ın Nesnelerle Çalışma kılavuzuna göz atın.
Örnek
şunu çağırmak istediğinizi varsayalım: sizeWithFont:forWidth:lineBreakMode:
seçicisi üzerinde NSString
.
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ü Birleşik API'ye yöneliktir
CGSize
. font
parametresi, NSObject'ten türetilen bir UIFont (ve (dolaylı) türüdür ve System.IntPtr ile eşlenir.width
parametresi ileCGFloat
eşlenirnfloat
.lineBreakMode
parametresi,UILineBreakMode
Xamarin.iOS'ta zatenUILineBreakMode
Numaralandırma.
Hepsini bir araya getirmek için bildirimin eşleşmesi objc_msgSend
gerekir:
CGSize objc_msgSend(
IntPtr target,
IntPtr selector,
IntPtr font,
nfloat width,
UILineBreakMode mode
);
Bunu aşağıdaki gibi bildirin:
[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ğırmak için 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ğerin boyutu 8 bayttan küçük bir yapı olsaydı (Birleşik API'lere geçmeden önce kullanılan eski SizeF
gibi), yukarıdaki kod simülatörde çalışır ancak cihazda kilitlenebilirdi. Boyutu 8 bitten küçük bir değer döndüren bir seçiciyi çağırmak için işlevini bildirin objc_msgSend_stret
:
[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ğırmak için 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çici çağırma
Bir seçiciyi çağırmanın üç adımı vardır:
- Seçici hedefini alın.
- Seçici adını alın.
- Uygun bağımsız değişkenlerle çağrısı
objc_msgSend
yapın.
Seçici hedefleri
Seçici hedefi bir nesne örneği veya Objective-C sınıftır. Hedef bir örnekse ve ilişkili bir Xamarin.iOS türünden geldiyse özelliğini kullanın ObjCRuntime.INativeObject.Handle
.
Hedef bir sınıfsa, ObjCRuntime.Class
sınıf örneğine başvuru almak için öğesini kullanın ve ardından özelliğini kullanın Class.Handle
.
Seçici adları
Seçici adları Apple belgelerinde listelenmiştir. Örneğin, NSString
ve seçicileri içerir sizeWithFont:
sizeWithFont:forWidth:lineBreakMode:
. Eklenmiş ve sondaki iki nokta üst üsteler seçici adının bir parçasıdır ve atlanamaz.
Seçici adını aldıktan sonra bunun için bir ObjCRuntime.Selector
örnek oluşturabilirsiniz.
arama objc_msgSend
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 (ö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 olmalıdır System.IntPtr
ve kalan tüm bağımsız değişkenler seçicinin beklediği türle (örneğinnint
, bir int
için veya tüm NSObject
türetilmiş türler için) System.IntPtr
eşleşmelidir. kullanınNSObject.Handle
bir tür örneği için bir IntPtr
elde etmek için Objective-C özelliği.
Birden objc_msgSend
fazla işlev vardır:
- Yapı döndüren seçiciler için kullanın
objc_msgSend_stret
. ARM'de bu, numaralandırma olmayan tüm dönüş türlerini veya C yerleşik türlerinden herhangi birini (char
,short
,int
,long
, ,float
)double
içerir. x86'da (simülatör), bu yöntemin boyutu 8 bayttan büyük tüm yapılar için kullanılması gerekir (CGSize
8 bayttır ve simülatörde kullanılmazobjc_msgSend_stret
). - Yalnızca x86 üzerinde kayan nokta değeri döndüren seçiciler için kullanın
objc_msgSend_fpret
. Bu işlevin ARM'de kullanılması gerekmez; bunun yerine kullanınobjc_msgSend
. - Ana objc_msgSend işlevi diğer tüm seçiciler için kullanılır.
Hangi işlevleri çağırmanız gerektiğini belirledikten objc_msgSend
sonra (simülatör ve cihazların her biri farklı bir yöntem gerektirebilir), işlevi daha sonra çağırmak üzere bildirmek için normal [DllImport]
bir yöntem kullanabilirsiniz.
Önceden oluşturulmuş objc_msgSend
bir bildirim kümesi içinde ObjCRuntime.Messaging
bulunabilir.
Simülatörde ve cihazda farklı çağrılar
Yukarıda açıklandığı gibi, Objective-C üç tür objc_msgSend
yöntem vardır: biri normal çağrılar için, biri kayan nokta değerleri döndüren çağrılar için (yalnızca x86) ve biri de yapı değerleri döndüren çağrılar için. İkincisi, içinde ObjCRuntime.Messaging
son eki _stret
içerir.
Belirli yapıları döndürecek bir yöntemi çağırırsanız (aşağıda açıklanan kurallar), dönüş değeriyle yöntemi ilk parametre olarak bir out
değer olarak çağırmanız gerekir:
// 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öntemin ne zaman kullanılacağına ilişkin _stret_
kural x86 ve ARM'de farklılık gösterir.
Bağlamalarınızın hem simülatörde hem de cihazda çalışmasını istiyorsanız, 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 yöntemini kullanma
ARM için oluştururken objc_msgSend_stret
sabit listesi olmayan herhangi bir değer türü veya sabit listesi (int
, , byte
, short
, long
, double
float
) için temel türlerden herhangi biri için.
x86 için oluştururken objc_msgSend_stret
sabit listesi olmayan veya bir sabit listesi (int
, , byte
, short
, long
, double
float
) için temel türlerden herhangi biri olmayan ve yerel boyutu 8 bayttan büyük olan herhangi bir değer türü için.
Kendi imzalarınızı oluşturma
Aşağıdaki gist, gerekirse kendi imzalarınızı oluşturmak için kullanılabilir.