Selektor di Objective-C?

122

Pertama, saya tidak yakin saya benar-benar mengerti apa itu selector. Dari pemahaman saya, itu adalah nama metode, dan Anda dapat menetapkannya ke kelas tipe 'SEL' dan kemudian menjalankan metode seperti respondToSelector untuk melihat apakah penerima mengimplementasikan metode itu. Bisakah seseorang memberikan penjelasan yang lebih baik?

Kedua, untuk poin ini, saya memiliki kode berikut:

NSString *thing = @"Hello, this is Craig";

SEL sel = @selector(lowercaseString:);
NSString *lower = (([thing respondsToSelector:sel]) ? @"YES" : @"NO");
NSLog (@"Responds to lowercaseString: %@", lower);
if ([thing respondsToSelector:sel]) //(lower == @"YES")
    NSLog(@"lowercaseString is: %@", [thing lowercaseString]);

Namun, meskipun thingjelas merupakan jenis NSString, dan harus merespons lowercaseString, saya tidak bisa mendapatkan 'respondsToSelector' bersyarat untuk mengembalikan "YA" ...

Craig
sumber
Anda ingin membaca deskripsi Selector di situs pengembang Apple: Selectors .
lothar 10
14
Kursus Stanford tugas CS193P 1B? Saya punya pertanyaan yang persis sama di sini! :)
Corstian Boerman

Jawaban:

181

Anda harus sangat berhati-hati dengan nama metode. Dalam kasus ini, nama metode hanya " lowercaseString", bukan " lowercaseString:" (perhatikan tidak adanya titik dua). Itulah mengapa Anda NOdikembalikan, karena NSStringobjek menanggapi lowercaseStringpesan tetapi bukan lowercaseString:pesannya.

Bagaimana Anda tahu kapan harus menambahkan titik dua? Anda menambahkan titik dua ke nama pesan jika Anda ingin menambahkan titik dua saat memanggilnya, yang terjadi jika diperlukan satu argumen. Jika dibutuhkan nol argumen (seperti halnya dengan lowercaseString), maka tidak ada titik dua. Jika dibutuhkan lebih dari satu argumen, Anda harus menambahkan nama argumen tambahan bersama dengan titik dua, seperti pada compare:options:range:locale:.

Anda juga dapat melihat dokumentasi dan mencatat ada atau tidaknya tanda titik dua.

Adam Rosenfield
sumber
12

Selektor adalah cara yang efisien untuk mereferensikan metode secara langsung dalam kode yang dikompilasi - kompilator adalah yang sebenarnya memberikan nilai ke SEL.

Orang lain telah menutupi bagian kedua dari q Anda, ':' di bagian akhir cocok dengan tanda tangan yang berbeda dari yang Anda cari (dalam hal ini tanda tangan itu tidak ada).

dstnbrkr.dll
sumber
10

Itu karena kamu mau @selector(lowercaseString), bukan @selector(lowercaseString:). Ada perbedaan halus: yang kedua menyiratkan parameter (perhatikan titik dua di akhir), tetapi - [NSString lowercaseString]tidak mengambil parameter.

mipadi
sumber
5

Dalam kasus ini, nama pemilih salah. Titik dua di sini adalah bagian dari tanda tangan metode; itu berarti bahwa metode tersebut membutuhkan satu argumen. Saya percaya yang Anda inginkan

SEL sel = @selector(lowercaseString);
mkb
sumber
3

Metode NSString adalah lowercaseString(0 argumen), bukan lowercaseString:(1 argumen).

Nicholas Riley
sumber
1

Jangan anggap titik dua sebagai bagian dari nama fungsi, anggap saja sebagai pemisah, jika Anda tidak memiliki apa pun untuk dipisahkan (tidak ada nilai yang sesuai dengan fungsi) maka Anda tidak membutuhkannya.

Saya tidak yakin mengapa tetapi semua hal OO ini tampaknya asing bagi pengembang Apple. Saya sangat menyarankan untuk menggunakan Visual Studio Express dan bermain-main dengannya juga. Bukan karena yang satu lebih baik dari yang lain, hanya itu cara yang baik untuk melihat masalah desain dan cara berpikir.

Suka

introspection = reflection
+ before functions/properties = static
- = instance level

Itu selalu bagus untuk melihat masalah dengan cara yang berbeda dan pemrograman adalah teka-teki pamungkas.


sumber
0

Dari pemahaman saya tentang dokumentasi Apple, pemilih mewakili nama metode yang ingin Anda panggil. Hal yang menyenangkan tentang penyeleksi adalah Anda dapat menggunakannya dalam kasus di mana metode yang tepat untuk dipanggil bervariasi. Sebagai contoh sederhana, Anda dapat melakukan sesuatu seperti:

SEL selec;
if (a == b) {
selec = @selector(method1)
}
else
{
selec = @selector(method2)
};
[self performSelector:selec];
moonman239
sumber
0

Sesuai dokumen apple: https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/Selector.html

Selektor adalah nama yang digunakan untuk memilih metode yang akan dieksekusi untuk objek, atau pengenal unik yang menggantikan nama saat kode sumber dikompilasi. Seorang pemilih dengan sendirinya tidak melakukan apapun. Ini hanya mengidentifikasi sebuah metode. Satu-satunya hal yang membuat nama metode pemilih berbeda dari string biasa adalah kompilator memastikan bahwa penyeleksi unik. Apa yang membuat pemilih berguna adalah (dalam hubungannya dengan runtime) bertindak seperti penunjuk fungsi dinamis yang, untuk nama tertentu, secara otomatis menunjuk ke implementasi metode yang sesuai untuk kelas mana pun yang digunakan. Misalkan Anda memiliki pemilih untuk menjalankan metode, dan kelas Dog, Athlete, dan ComputerSimulation (masing-masing menerapkan metode run).

Contoh: (lldb) breakpoint --set selector viewDidLoad

Ini akan menyetel breakpoint pada semua implementasi viewDidLoad di aplikasi Anda. Jadi selector adalah semacam pengenal global untuk sebuah metode.

Adrian
sumber