【问题标题】:Objective-C set default value for a propertyObjective-C 设置属性的默认值
【发布时间】:2012-04-07 11:43:45
【问题描述】:

我正在制作一个应用程序,我有一个包含很多属性的类,我想知道是否可以给它们一个默认值。因为如果我创建一个 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;}
}

【问题讨论】:

    标签: objective-c properties default-value


    【解决方案1】:

    是的,您可以覆盖 getter,以防在属性被初始化之前设置默认值。

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

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

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

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

    【讨论】:

    • 要求您的财产永远不能使用明确的0,因为它永远不会使用该代码返回0。此外,您可以将代码简化为 return _systemFontOfSize ?: 17.0f;
    【解决方案2】:
    - (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 函数中进行。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

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

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

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

        您也可以使用 c 样式的结构,因为这些只是原语。

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

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

        您可以将配置拆分为不同的类型(守门员、技术和心理)。同样,这只是分散问题,但这有助于保持重点。

        【讨论】:

          【解决方案5】:

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

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

          然后这样称呼它:

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

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

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

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

          【讨论】:

          • 没错——初始化器是为 ivar 或属性设置初始值的好地方。更具体地说,指定的初始化程序(该类的任何其他初始化程序将调用的初始化程序)是您应该设置这些值的位置。
          • 感谢您的建议,但是,我试图避免在初始化程序中放置 30 多个赋值,并且不能真正拆分类(当然,它总是可以,但它只会让我的课程设计更糟)。
          • 为什么要避免我没有得到。 init 就是为此目的而创建的,或者您可以使用必须在 init 中设置的 Dictionary...
          • 应该提到,根据 Apple 手册,您不应该通过 init/dealloc 中的访问器方法访问属性。 developer.apple.com/library/mac/documentation/Cocoa/Conceptual/…
          • 缺点是您必须在每个初始化程序中执行此操作,或者正确链接初始化程序以相互调用,但无论哪种方式都有出错的余地。如果有适当的属性默认值,则不必担心。
          【解决方案6】:

          Objective C 中没有类似 Java 的内置方式来初始化综合属性 ivars。但是,由于您的属性看起来几乎相同,您可能需要考虑将它们改为 @dynamic合成它们。

          当然,您需要编写两个看起来很吓人的方法(here is a nice and clean example 为您服务),但作为回报,您将获得一种将属性作为对象存储在 NSMutableDictionary 中的统一方法。这开辟了一些普通 ivars 不可用的有趣替代方案:您可以推迟初始化您的属性,直到需要它们,您可以为未设置的属性提供默认值,或者您可以通过以下方式“批发”初始化您的属性用他们的键值填充字典。

          【讨论】:

          • 看起来很有趣,我明天去研究一下,谢谢!
          【解决方案7】:

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

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

          【讨论】:

          • +1,以后词典也更容易扩展和更改。
          • 但是如果你想在字典中存储混合类型的属性呢?
          • @To1ne 这应该不是问题。 NSDictionary 不强制类型安全。您可以存储多种类型的对象。
          猜你喜欢
          • 2011-03-21
          • 1970-01-01
          • 1970-01-01
          • 2011-12-11
          • 1970-01-01
          • 1970-01-01
          • 2012-03-07
          • 1970-01-01
          • 2010-10-16
          相关资源
          最近更新 更多