【问题标题】:extend class in objective-c with variable based property [duplicate]使用基于变量的属性扩展objective-c中的类[重复]
【发布时间】:2020-11-07 05:08:58
【问题描述】:

我在 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 类?

【问题讨论】:

  • self.formItemId[self formItemId] 的语法糖,self.formItemId = formItemId[self setFormItemId:formItemId] 的语法糖。

标签: objective-c oop objective-c-category


【解决方案1】:

你可以

@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,该 setter 将一次又一次地设置相同的值,也就是无限循环。 您可以按照上面所示的相同方式处理 getter。

那么在哪里使用self.yourProperty
您可以在类中的任何位置使用self.formItemId,但不能在formItemId 的getter 和setter 中使用。

说得对,实例变量不能放在类别中。 这意味着如果您需要这样,您必须将 UIControl 子类化,但这会破坏您使用的 UIControls 的继承。您必须将以后使用的所有 SpecialUIControl 子类化。

另一种解决方案,您可以在实现中定义一个常量,并使用 Objective-C 运行时函数并自己关联该常量。请注意,因为您随后会为所有 UIControl 类转换 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

不过,将您自己的 UIControl 子类化而不是扩展从 UIControl 继承的所有子类会更容易、更安全、更灵活。
为什么在这里子类化更容易?
正如您所提到的,您希望稍后使用给定的每个控件的 formItemId 进行 json,您可以使用您的子类的归档器/取消归档器设计模式,这很适合以后进行 jsonify。

【讨论】:

  • 不幸的是@synthesize 不允许在类别的实现中
  • _formItemId 声明在哪里?
  • 第一个例子中_formItemId在哪里声明?
猜你喜欢
  • 2013-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-16
  • 2020-03-28
  • 2021-12-23
  • 1970-01-01
  • 2016-08-10
相关资源
最近更新 更多