Objective-C 为属性设置默认值



我正在制作一个应用程序,我有一个具有很多属性的类,我想知道是否可以给它们一个默认值。因为如果我制作一个 init 方法,键入所有内容需要大量工作,很有可能出现错别字,而且编码不好......

这是我的班级的样子:

// Goalkeeping attributes
@property (nonatomic) int aerialAbility;
@property (nonatomic) int commandOfArea;
@property (nonatomic) int communication;
@property (nonatomic) int eccentricity;
@property (nonatomic) int handling;
@property (nonatomic) int kicking;
@property (nonatomic) int oneOnOnes;
@property (nonatomic) int reflexes;
@property (nonatomic) int rushingOut;
@property (nonatomic) int tendencyToPunch;
@property (nonatomic) int throwing;
// Technical attributes
@property (nonatomic) int corners;
@property (nonatomic) int crossing;
@property (nonatomic) int dribbling;
@property (nonatomic) int finishing;
@property (nonatomic) int firstTouch;
@property (nonatomic) int freeKickTaking;
@property (nonatomic) int heading;
@property (nonatomic) int longShots;
@property (nonatomic) int longThrows;
@property (nonatomic) int marking;
@property (nonatomic) int passing;
@property (nonatomic) int penaltyTaking;
@property (nonatomic) int tackling;
@property (nonatomic) int technique;
// Mental attributes
@property (nonatomic) int aggression;
@property (nonatomic) int anticipation;
@property (nonatomic) int bravery;
@property (nonatomic) int composure;
@property (nonatomic) int concentration;
@property (nonatomic) int creativity;
@property (nonatomic) int decisions;
@property (nonatomic) int determination;
@property (nonatomic) int flair;
@property (nonatomic) int influence;
@property (nonatomic) int offTheBall;
@property (nonatomic) int positioning;
@property (nonatomic) int teamwork;
@property (nonatomic) int workRate;
// Physical attributes
@property (nonatomic) int acceleration;
@property (nonatomic) int agility;
@property (nonatomic) int balance;
@property (nonatomic) int jumping;
@property (nonatomic) int naturalFitness;
@property (nonatomic) int pace;
@property (nonatomic) int stamina;
@property (nonatomic) int strength;

因此,在实现中,我正在做类似的事情:

@synthesize aerialAbility = _aerialAbility;

我想知道是否有可能这样做:

@interface MyClass : NSObject
@property (nonatomic) int someProperty;
@end
@implementation MyClass
@synthesize someProperty = _someProperty = 10;
@end

我知道这行不通,这根本不对,但我想知道是否有办法做这样的事情。

就像在java中一样,你可以:

class MyClass
{
private int someProperty = 10;
public int getSomeProperty(){return someProperty;}
public void setSomeProperty(int someProperty){this.someProperty = someProperty;}
}

我以前从未见过这种行为,但我很确定这就是分配对象时的 init 步骤,即设置变量和初始化对象。

-(id)init {
     if (self = [super init])  {
       self.someProperty = 10;
     }
     return self;
}

并像这样称呼它:

MyClass* test = [[MyClass alloc] init];

请注意,您可以有多个 init 函数,该函数允许您拥有几组不同的默认值。

@synthesize所做的是告诉预编译器它应该为 set/get 生成代码,而不是设置属性的值。'=' 只是告诉预编译器,即使变量和属性的名称不同,它们也应该连接起来。

此外,作为个人意见(根本没有意识到这个问题(,这个对象似乎很大,你可以以某种方式将其拆分或像其他人建议的那样。也许这个类可以从其他几个类继承,给它所需的不同属性?正如我所说,这只是一个建议,因为我不知道您的其他代码是什么样子的:)

对于如此大量的属性,我倾向于将数据存储为字典而不是单个属性,并且我会将默认值存储在属性列表中。 NSDictionary对象可以使用属性列表轻松初始化。

如果使用字典不符合您的口味,我仍然会将默认值存储在属性列表中,并且在指定的初始化器中,我会遍历属性列表中的项目并使用键值编码将它们应用于self。 您应该注意,这仅适用于受信任的数据,不适用于用户提供的数据,否则它可能会被劫持以设置您不希望的其他属性。

在 Objective C 中没有内置的类似 Java 的方式来初始化合成属性 ivar。但是,由于属性看起来几乎相同,因此您可能需要考虑使它们@dynamic而不是合成它们。

当然,您需要编写两个看起来很吓人的方法(这是一个不错且干净的示例(,但作为回报,您将获得一种统一的方式来将属性存储为NSMutableDictionary中的对象。这开辟了几个普通 ivars 无法提供的有趣替代方案:您可以推迟属性的初始化,直到需要它们,您可以为未设置的属性提供默认值,或者您可以通过在字典中填写其键的值来"批发"初始化您的属性。

是的,您可以在启动属性之前设置默认值的情况下覆盖 getter。

例如,在 .h 文件中定义属性:

@interface MySegmentedControl : UISegmentedControl
@property (assign, nonatomic) CGFloat systemFontOfSize;
@end

并覆盖 getter 并在 .m 文件中的实现下设置默认值:

@implementation MySegmentedControl    
-(CGFloat) systemFontOfSize
{
    return _systemFontOfSize ? _systemFontOfSize : 17.0f;
}    
@end

上面的字典建议是一个很好的建议。 我有时会使用专用的配置对象:

@interface GoalKeepingAttributes
@property (nonatomic) int agression
@property (nonatomic) int ... etc
@end
@implementation GoalKeepingAttributes
@end

等。 如果需要,此类可以有一个 init 方法来设置一堆值和默认值。

您可能也可以使用 c 样式结构,因为这些只是基元。

确实,这只是推迟问题,将初始化从一个类移动到配置类,但是:

  • 无论如何,您都必须使用字典来执行此操作
  • 您可以注释配置设置
  • 最大的胜利:config 类是强类型的,它在编译时捕获错误,允许 Xcode 代码完成

您可以将配置分为不同的类型(守门员、技术和心理(。 同样,它只是将问题分开,但这可以帮助保持专注。

另一种可能性是覆盖属性的默认 getter。 在 getter 中,您可以查看值是否已初始化,如果没有,则返回默认值。 (显然,这适用于某些属性类型,但不适用于其他属性类型 - 您需要默认值是指示未设置任何值的值。

- (id)init
{
    self = [super init];
    if (self != nil) {
        [self commonInit];
    }
    return self;
}
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self != nil) {
        [self commonInit];
    }
    return self;
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder { //nib init
    self = [super initWithCoder:aDecoder];
    if (self != nil) {
        [self commonInit];
    }
    return self;
}

如果对象是视图,则可以设置默认值并在 commonInit 函数中执行默认逻辑。如果不是视图,我认为您可以在 init 函数中执行此操作。

最新更新