Dengan asumsi bahwa saya memiliki typedef yang dinyatakan dalam file .h saya seperti:
typedef enum {
JSON,
XML,
Atom,
RSS
} FormatType;
Saya ingin membangun fungsi yang mengubah nilai numerik dari typedef menjadi string. Misalnya, jika pesan [self toString:JSON]
itu dikirim; itu akan mengembalikan 'JSON'.
Fungsi akan terlihat seperti ini:
-(NSString *) toString:(FormatType)formatType {
//need help here
return [];
}
Kebetulan, kalau saya coba sintaks ini
[self toString:FormatType.JSON];
untuk meneruskan nilai typedef ke metode, saya mendapatkan kesalahan. Apa yang saya lewatkan?
c
objective-c
enums
typedef
craig
sumber
sumber
Jawaban:
Ini benar-benar pertanyaan C, tidak spesifik untuk Objective-C (yang merupakan superset dari bahasa C). Enum dalam C direpresentasikan sebagai bilangan bulat. Jadi, Anda perlu menulis fungsi yang mengembalikan string yang diberi nilai enum. Ada banyak cara untuk melakukan ini. Array string sehingga nilai enum dapat digunakan sebagai indeks ke dalam array atau struktur peta (misalnya an
NSDictionary
) yang memetakan nilai enum ke kerja string, tapi saya menemukan bahwa pendekatan ini tidak sejelas fungsi yang membuat konversi eksplisit (dan pendekatan array, meskipunC
cara klasik berbahaya jika nilai enum Anda tidak bertentangan dengan 0). Sesuatu seperti ini akan berhasil:Pertanyaan terkait Anda tentang sintaks yang benar untuk nilai enum adalah bahwa Anda hanya menggunakan nilai (misalnya
JSON
), bukanFormatType.JSON
sytax.FormatType
adalah tipe dan nilai enum (misJSON
.XML
, dll.) adalah nilai yang dapat Anda tetapkan untuk tipe itu.sumber
Anda tidak dapat melakukannya dengan mudah. Dalam C dan Objective-C, enum adalah konstanta integer yang dimuliakan. Anda harus membuat sendiri daftar nama (atau dengan beberapa penyalahgunaan preprosesor). Sebagai contoh:
Bahaya dari pendekatan ini adalah bahwa jika Anda pernah mengubah enum, Anda harus ingat untuk mengubah susunan nama. Anda dapat memecahkan masalah ini dengan beberapa penyalahgunaan preprosesor, tetapi rumit dan jelek.
Perhatikan juga bahwa ini mengasumsikan Anda memiliki konstanta enum yang valid. Jika Anda memiliki nilai integer dari sumber yang tidak terpercaya, Anda juga perlu melakukan pengecekan bahwa konstanta Anda valid, misalnya dengan memasukkan nilai "max masa lalu" dalam enum Anda, atau dengan memeriksa apakah itu kurang dari panjang array
sizeof(FormatType_toString) / sizeof(FormatType_toString[0])
,.sumber
string[] = { [XML] = "XML" }
untuk memastikan string cocok dengan enum dengan benarFormatType_toString[]
array dan memanggil-isEqualToString:
setiap elemen untuk menemukan kecocokan, atau menggunakan tipe data pemetaan sepertiNSDictionary
untuk mempertahankan peta pencarian terbalik.FormatType_toString
array.Solusi saya:
edit: Saya telah menambahkan solusi yang lebih baik di akhir, menggunakan Modern Obj-C
1.
Masukkan nama sebagai kunci dalam array.
Pastikan indeks adalah enum yang sesuai, dan dalam urutan yang benar (kecuali pengecualian).
note: names adalah properti yang disintesis sebagai * _names *;
kode tidak diperiksa untuk kompilasi, tetapi saya menggunakan teknik yang sama di aplikasi saya.
//
2.
Menggunakan Modern Obj-C Anda, kami dapat menggunakan kamus untuk mengikat deskripsi ke kunci di enum.
Memesan tidak masalah .
Penggunaan (dalam metode instance kelas):
sumber
+[typeDisplayNames]
, Anda membuat kembali kamus. Ini bagus jika hanya dipanggil beberapa kali, tetapi jika dipanggil berkali-kali, ini akan menjadi sangat mahal. Solusi yang lebih baik mungkin membuat kamus menjadi singleton, jadi itu hanya dibuat sekali dan tetap di memori sebaliknya. Memori klasik vs. teka-teki CPU.static NSDictionary *dict = nil; if(!dict) dict = @{@(UserTypeParent): @"Parent"}; return dict;
Komentar tidak akan membiarkan Anda memutuskan, maaf untuk itu.Menggabungkan jawaban @AdamRosenfield, komentar @Christoph dan trik lain untuk menangani enum C sederhana saya sarankan:
Dalam kasus terburuk - seperti jika Anda mengubah enum tetapi lupa untuk mengubah array nama - itu akan mengembalikan nol untuk kunci ini.
sumber
define typedef enum di header kelas:
tulis metode seperti ini di kelas:
memiliki string di dalam file Localizable.strings :
sumber
Saya akan menggunakan token # string kompiler (bersama dengan makro untuk membuatnya lebih kompak):
sumber
Saya suka
#define
cara melakukan ini:// Letakkan ini di file .h Anda, di luar blok @interface
sumber(sumber tidak lagi tersedia)sumber
nil
kalau kembali kalauarray.count <= enumValue
?Saya membuat semacam campuran dari semua solusi yang ditemukan di halaman ini untuk membuat milik saya, itu semacam ekstensi enum berorientasi objek atau sesuatu.
Bahkan jika Anda membutuhkan lebih dari sekadar konstanta (yaitu bilangan bulat), Anda mungkin memerlukan objek model (Kita semua berbicara tentang MVC, bukan?)
Cukup tanyakan pada diri Anda pertanyaan sebelum menggunakan ini, apakah saya benar, bukankah Anda, pada kenyataannya, membutuhkan objek model nyata, diinisialisasi dari layanan web, sebuah plist, database SQLite atau CoreData?
Pokoknya inilah kode (MPI adalah untuk "Inisial Proyek Saya", tampaknya semua orang menggunakan ini atau nama mereka):
MyWonderfulType.h
:Dan
MyWonderfulType.m
:sumber
Solusi lain:
Dalam metode Anda, Anda dapat menggunakan:
sumber
Jawaban @ yar1vn yang ditingkatkan dengan menjatuhkan ketergantungan string:
Dengan demikian ketika Anda akan mengubah nama entri enum string yang sesuai akan diubah. Berguna jika Anda tidak akan menampilkan string ini kepada pengguna.
sumber
"foo""bar"
, itu menghasilkan string"foobar"
ketika dikompilasi. Jadi,#define VariableName(arg) (@""#arg)
akan berkembangVariableName(MyEnum)
menjadi(@"""MyEnum")
. Itu akan menghasilkan string@"MyEnum"
.Diberikan definisi enum seperti:
Kita bisa mendefinisikan makro untuk mengonversi nilai enum ke string yang sesuai, seperti yang ditunjukkan di bawah ini.
The
switch
pernyataan yang digunakan di blok adalah untuk memeriksa jenis, dan juga untuk mendapatkan dukungan auto-lengkap dalam Xcode.sumber
Saya memiliki tipe enumerasi besar yang ingin saya ubah menjadi
NSDictionary
pencarian. Saya akhirnya menggunakansed
dari terminal OSX sebagai:yang dapat dibaca sebagai: 'tangkap kata pertama pada baris dan hasilkan @ (kata): @ "kata",'
Regex ini mengonversi enum dalam file header bernama 'ObservationType.h' yang berisi:
menjadi sesuatu seperti:
yang kemudian dapat dibungkus dengan metode menggunakan sintaks objektif-c modern
@{ }
(seperti yang dijelaskan oleh @ yar1vn di atas) untuk membuatNSDictionary
pencarian:The
dispatch_once
boiler-piring hanya untuk memastikan bahwa variabel statis dijalankan dengan cara benang-aman.Catatan: Saya menemukan ekspresi sed regex di OSX aneh - ketika saya mencoba menggunakan
+
untuk mencocokkan 'satu atau lebih' itu tidak berfungsi dan harus menggunakan{1,}
sebagai penggantisumber
Saya menggunakan variasi pada jawaban Barry Walk, yang berurutan:
MISALNYA:
sumber
@pixel menambahkan jawaban paling cemerlang di sini: https://stackoverflow.com/a/24255387/1364257 Tolong, upvote dia!
Dia menggunakan makro X yang rapi dari tahun 1960-an. (Saya telah sedikit mengubah kodenya untuk ObjC modern)
Itu dia. Bersih dan rapi. Terima kasih kepada @pixel! https://stackoverflow.com/users/21804/pixel
sumber
Saya menggabungkan beberapa pendekatan di sini. Saya suka ide preprocessor dan daftar yang diindeks.
Tidak ada alokasi dinamis tambahan, dan karena penyusun kompiler mungkin dapat mengoptimalkan pencarian.
sumber
Pertama-tama, berkenaan dengan FormatType.JSON: JSON bukan anggota dari FormatType, itu adalah nilai yang mungkin dari tipe tersebut. FormatType bahkan bukan tipe komposit - itu skalar.
Kedua, satu-satunya cara untuk melakukan ini adalah membuat tabel pemetaan. Cara yang lebih umum untuk melakukan ini di Objective-C adalah dengan membuat serangkaian konstanta yang mengacu pada "simbol" Anda, jadi Anda harus
NSString *FormatTypeJSON = @"JSON"
dan seterusnya.sumber
berikut ini memberikan solusi sehingga untuk menambahkan enum baru hanya memerlukan satu baris edit, pekerjaan yang mirip dengan menambahkan satu baris dalam daftar enum {}.
sumber
Setiap jawaban di sini pada dasarnya mengatakan hal yang sama, membuat enum reguler dan kemudian menggunakan pengambil kustom untuk beralih di antara string.
Saya menggunakan solusi yang jauh lebih sederhana yang lebih cepat, lebih pendek, dan lebih bersih — menggunakan Macro!
Kemudian Anda bisa mulai mengetik
kNam...
dan pengisian otomatis akan menampilkan daftar yang Anda inginkan!Selain itu, jika Anda ingin menangani logika untuk semua nama sekaligus, Anda dapat dengan cepat mencacah array literal secara berurutan, sebagai berikut:
for (NSString *kName in kNames_allNames) {}
Terakhir, casting NSString di makro memastikan perilaku yang mirip dengan typedef!
Nikmati!
sumber
Banyak jawaban semua cukup bagus.
Jika Anda mencari generik, solusi Objective C yang menggunakan beberapa makro ...
Fitur utamanya adalah ia menggunakan enum sebagai indeks ke dalam array statis konstanta NSString. array itu sendiri dibungkus menjadi suatu fungsi untuk membuatnya lebih seperti rangkaian fungsi NSStringFromXXX yang lazim di Apple API.
Anda perlu
#import "NSStringFromEnum.h"
ditemukan di sini http://pastebin.com/u83RR3Vk[EDIT] juga perlu
#import "SW+Variadic.h"
ditemukan di sini http://pastebin.com/UEqTzYLfContoh 1: mendefinisikan sepenuhnya enum typedef BARU, dengan konverter string.
di myfile.h
di myfile.m:
menggunakan :
NSStringFromEnumDispatch_chain_cmd(chain_for_c)
kembali@"chain_for_c"
enumDispatch_chain_cmdFromNSString(@"chain_previous")
kembalichain_previous
Contoh 2: menyediakan rutinitas konversi untuk enum yang ada juga menunjukkan menggunakan string pengaturan, dan mengganti nama nama pengguna yang digunakan dalam fungsi.
di myfile.h
di myfile.m:
sumber
Ini berfungsi -> https://github.com/ndpiparava/ObjcEnumString
sumber
Bergantung pada kebutuhan Anda, Anda dapat menggunakan arahan kompiler sebagai alternatif untuk mensimulasikan perilaku yang Anda cari.
Ingat saja kekurangan kompiler yang biasa, (bukan tipe aman, langsung salin-tempel membuat file sumber lebih besar)
sumber
#define
terlihat, Anda tidak akan dapat menggunakan nilai enum yang sebenarnya (yaituJSON
akan diganti dengan@"JSON"
oleh preprocessor dan akan menghasilkan kesalahan kompiler ketika menetapkan keFormatType
.