Câu trả lời đưa ra hoạt động rất tốt và đề xuất của tôi chỉ là một phần mở rộng cho nó mà tránh viết quá nhiều mã soạn sẵn.
Để tránh việc viết nhiều lần phương thức getter và setter cho các thuộc tính thể loại, câu trả lời này giới thiệu các macro. Ngoài ra, các macro này dễ dàng sử dụng các thuộc tính loại nguyên thủy như int
hoặc BOOL
.
Phương pháp truyền thống không có macro
Theo truyền thống, bạn xác định một thuộc tính danh mục như
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
Sau đó, bạn cần triển khai phương thức getter và setter bằng cách sử dụng một đối tượng được liên kết và bộ chọn get làm khóa ( xem câu trả lời gốc ):
#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
Cách tiếp cận được đề xuất của tôi
Bây giờ, sử dụng một macro bạn sẽ viết thay thế:
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
Các macro được định nghĩa như sau:
#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)
Macro CATEGORY_PROPERTY_GET_SET
thêm một getter và setter cho thuộc tính đã cho. Thuộc tính chỉ đọc hoặc chỉ ghi sẽ sử dụng tương ứng CATEGORY_PROPERTY_GET
và CATEGORY_PROPERTY_SET
macro.
Các kiểu nguyên thủy cần chú ý hơn một chút
Vì các kiểu nguyên thủy không có đối tượng, các macro ở trên chứa một ví dụ để sử dụng unsigned int
làm kiểu của thuộc tính. Nó làm như vậy bằng cách gói giá trị nguyên vào một NSNumber
đối tượng. Vì vậy, cách sử dụng của nó là tương tự như ví dụ trước:
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
Sau mô hình này, bạn chỉ có thể bổ sung thêm các macro cũng để hỗ trợ signed int
, BOOL
, vv ...
Hạn chế
Tất cả các macro đang sử dụng OBJC_ASSOCIATION_RETAIN_NONATOMIC
theo mặc định.
Các IDE như Mã ứng dụng hiện không nhận ra tên của setter khi tái cấu trúc tên của thuộc tính. Bạn sẽ cần phải đổi tên nó một mình.