使用基于变量的 属性 在 objective-c 中扩展 class
extend class in objective-c with variable based property
我在 objective-c 中有一个表单实现,我想扩展我的小部件(NSButton、NSTextField 等)以包含额外的字符串,表示它们在提交后使用的唯一标识符字符串事件发生,触发生成 json 包含所有小部件 id/value 对。
我试过使用类别来扩展 NSControl,它是所有这些小部件的公共父级,如下所示。
NSControl+formItemSupport.h
-------------------------------
@interface NSControl (formItemSupport)
@property NSString * formItemId;
@end
NSControl+formItemSupport.m
-------------------------------
@implementation NSControl (formItemSupport)
-(NSString *)formItemId {
return self.formItemId;
}
-(void)setFormItemId:(NSString *)formItemId {
self.formItemId = formItemId;
}
在我从 NSControl+formItemSupport.m
导入的 form.m 文件中,但是当我尝试在 NSButton : NSControl
对象中设置此字段时。但是,当我尝试设置 属性 formItemId 时,我进入了无限循环。也许还有另一种方法可以在不使用继承的情况下使用基于变量的 属性 扩展 objc class ?
你可以
@synthesize formItemId = _formItemId;
//synthesize needs local declaration of _formItemId;
@implementation ExtraWurst {
NSString *_formItemId;
}
但这是在没有@synthesize 的情况下 Xcode 在幕后为您完成的。
有时以这种方式为 属性 定义内部变量的使用仍然更容易。
除此之外,您可以并且必须按以下方式更改 setter 和 getter 方法。
-(NSString *)formItemId {
return _formItemId;
}
-(void)setFormItemId:(NSString *)formItemId {
_formItemId = formItemId;
}
这将防止您陷入循环。
为什么?
因为 self.formItemId =
指的是 -(void)setFormItemId:
所以你会在 setter 中调用 setter ,它会一次又一次地设置相同的值,也就是无限循环。
您可以按照上述相同的方式处理 getter。
那self.yourProperty
用在什么地方?
您可以在 class 中的任何地方使用 self.formItemId
,但不能在 formItemId
的 getter 和 setter 内使用。
说的对,实例变量不能放在类别中。
这意味着如果你需要这样你必须 subclass UIControl 但这会破坏你使用的 UIControls 的继承。您必须将您以后使用的所有 SpecialUIControl 子class。
另一个解决方案,您可以在您的实现中定义一个常量,然后使用 objective-C 运行时函数并自己关联这个常量。当心,因为您为所有 UIControl classes 转换了 ObjectModel 然后..
#import "NSControl+formItemSupport.h"
#import <objc/runtime.h>
@implementation UIControl (formItemSupport)
NSString const *key = @"formItemSupport.forItemKey";
-(void)setFormItemId:(NSString *)formItemId {
objc_setAssociatedObject(self, &key, formItemId, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)formItemId {
return objc_getAssociatedObject(self, &key);
}
@end
不过,子class您自己的 UIControl 而不是扩展从 UIControl 继承的所有子class 更容易、更安全、更灵活。
为什么 subclassing 在这里更容易?
正如您提到的,您稍后想 json 使用给定的每个控件的 formItemId,您可以使用子 classes 的归档器/解档器设计模式,这很适合稍后 jsonify .
我在 objective-c 中有一个表单实现,我想扩展我的小部件(NSButton、NSTextField 等)以包含额外的字符串,表示它们在提交后使用的唯一标识符字符串事件发生,触发生成 json 包含所有小部件 id/value 对。
我试过使用类别来扩展 NSControl,它是所有这些小部件的公共父级,如下所示。
NSControl+formItemSupport.h
-------------------------------
@interface NSControl (formItemSupport)
@property NSString * formItemId;
@end
NSControl+formItemSupport.m
-------------------------------
@implementation NSControl (formItemSupport)
-(NSString *)formItemId {
return self.formItemId;
}
-(void)setFormItemId:(NSString *)formItemId {
self.formItemId = formItemId;
}
在我从 NSControl+formItemSupport.m
导入的 form.m 文件中,但是当我尝试在 NSButton : NSControl
对象中设置此字段时。但是,当我尝试设置 属性 formItemId 时,我进入了无限循环。也许还有另一种方法可以在不使用继承的情况下使用基于变量的 属性 扩展 objc class ?
你可以
@synthesize formItemId = _formItemId;
//synthesize needs local declaration of _formItemId;
@implementation ExtraWurst {
NSString *_formItemId;
}
但这是在没有@synthesize 的情况下 Xcode 在幕后为您完成的。
有时以这种方式为 属性 定义内部变量的使用仍然更容易。
除此之外,您可以并且必须按以下方式更改 setter 和 getter 方法。
-(NSString *)formItemId {
return _formItemId;
}
-(void)setFormItemId:(NSString *)formItemId {
_formItemId = formItemId;
}
这将防止您陷入循环。
为什么?
因为 self.formItemId =
指的是 -(void)setFormItemId:
所以你会在 setter 中调用 setter ,它会一次又一次地设置相同的值,也就是无限循环。
您可以按照上述相同的方式处理 getter。
那self.yourProperty
用在什么地方?
您可以在 class 中的任何地方使用 self.formItemId
,但不能在 formItemId
的 getter 和 setter 内使用。
说的对,实例变量不能放在类别中。 这意味着如果你需要这样你必须 subclass UIControl 但这会破坏你使用的 UIControls 的继承。您必须将您以后使用的所有 SpecialUIControl 子class。
另一个解决方案,您可以在您的实现中定义一个常量,然后使用 objective-C 运行时函数并自己关联这个常量。当心,因为您为所有 UIControl classes 转换了 ObjectModel 然后..
#import "NSControl+formItemSupport.h"
#import <objc/runtime.h>
@implementation UIControl (formItemSupport)
NSString const *key = @"formItemSupport.forItemKey";
-(void)setFormItemId:(NSString *)formItemId {
objc_setAssociatedObject(self, &key, formItemId, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)formItemId {
return objc_getAssociatedObject(self, &key);
}
@end
不过,子class您自己的 UIControl 而不是扩展从 UIControl 继承的所有子class 更容易、更安全、更灵活。
为什么 subclassing 在这里更容易?
正如您提到的,您稍后想 json 使用给定的每个控件的 formItemId,您可以使用子 classes 的归档器/解档器设计模式,这很适合稍后 jsonify .