Jawaban yang diberikan bekerja dengan baik dan proposal saya hanyalah perpanjangan dari itu yang menghindari penulisan terlalu banyak kode boilerplate.
Untuk menghindari penulisan berulang kali metode pengambil dan penyetel untuk properti kategori, jawaban ini memperkenalkan makro. Selain itu, makro ini memudahkan penggunaan properti tipe primitif seperti int
atau BOOL
.
Pendekatan tradisional tanpa makro
Secara tradisional Anda mendefinisikan properti kategori seperti
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Kemudian Anda perlu menerapkan metode pengambil dan penyetel menggunakan objek terkait dan pemilih get sebagai kuncinya ( lihat jawaban asli ):
#import <objc/runtime.h>
@implementation MyClass (Category)
- (NSString *)text{
return objc_getAssociatedObject(self, @selector(text));
}
- (void)setText:(NSString *)text{
objc_setAssociatedObject(self, @selector(text), text, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
Pendekatan yang saya sarankan
Sekarang, dengan menggunakan makro Anda akan menulis:
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
Makro ditentukan sebagai berikut:
#import <objc/runtime.h>
#define CATEGORY_PROPERTY_GET(type, property) - (type) property { return objc_getAssociatedObject(self, @selector(property)); }
#define CATEGORY_PROPERTY_SET(type, property, setter) - (void) setter (type) property { objc_setAssociatedObject(self, @selector(property), property, OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
#define CATEGORY_PROPERTY_GET_SET(type, property, setter) CATEGORY_PROPERTY_GET(type, property) CATEGORY_PROPERTY_SET(type, property, setter)
#define CATEGORY_PROPERTY_GET_NSNUMBER_PRIMITIVE(type, property, valueSelector) - (type) property { return [objc_getAssociatedObject(self, @selector(property)) valueSelector]; }
#define CATEGORY_PROPERTY_SET_NSNUMBER_PRIMITIVE(type, property, setter, numberSelector) - (void) setter (type) property { objc_setAssociatedObject(self, @selector(property), [NSNumber numberSelector: property], OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
#define CATEGORY_PROPERTY_GET_UINT(property) CATEGORY_PROPERTY_GET_NSNUMBER_PRIMITIVE(unsigned int, property, unsignedIntValue)
#define CATEGORY_PROPERTY_SET_UINT(property, setter) CATEGORY_PROPERTY_SET_NSNUMBER_PRIMITIVE(unsigned int, property, setter, numberWithUnsignedInt)
#define CATEGORY_PROPERTY_GET_SET_UINT(property, setter) CATEGORY_PROPERTY_GET_UINT(property) CATEGORY_PROPERTY_SET_UINT(property, setter)
Makro CATEGORY_PROPERTY_GET_SET
menambahkan pengambil dan penyetel untuk properti tertentu. Properti read-only atau write-only akan menggunakan makro CATEGORY_PROPERTY_GET
dan CATEGORY_PROPERTY_SET
masing-masing.
Tipe primitif membutuhkan lebih banyak perhatian
Karena tipe primitif bukan objek, makro di atas berisi contoh untuk digunakan unsigned int
sebagai tipe properti. Ia melakukannya dengan membungkus nilai integer ke dalam sebuah NSNumber
objek. Jadi penggunaannya analog dengan contoh sebelumnya:
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
Mengikuti pola ini, Anda hanya dapat menambahkan lebih banyak macro untuk juga mendukung signed int
, BOOL
, dll ...
Batasan
Semua makro digunakan OBJC_ASSOCIATION_RETAIN_NONATOMIC
secara default.
IDE seperti Kode Aplikasi saat ini tidak mengenali nama penyetel saat memfaktorkan ulang nama properti. Anda perlu mengganti namanya sendiri.