web-dev-qa-db-ja.com

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;}
}
29
Sander Declerck

私は以前にこの動作を見たことはありませんが、これは、変数を設定し、オブジェクトを初期化する、オブジェクトを割り当てるときのinitステップの目的であると確信しています。

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

そして、次のように呼び出します:

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

いくつかの異なるデフォルト値のセットを持つことができる複数のinit関数を持つことができることに注意してください。

@synthesizeが行うことは、プロパティの値を設定するのではなく、set/getのコードを生成する必要があることをプリコンパイラに伝えます。 '= "は、変数とプロパティの名前が同じでなくても、接続する必要があることをプリコンパイラーに伝えるだけです。

また、個人的な意見として(この質問にはまったく認識されていません)、このオブジェクトは大きく見えるようであり、何らかの方法で分割したり、他の人が提案したようにすることができます。このクラスは、他のいくつかのクラスから継承して、必要なさまざまなプロパティを与えることができますか?私が言ったように、あなたの他のコードがどのように見えるかわからないので、それは単なる提案です:)

48
chikuba

このような多数の属性の場合、個々のプロパティではなく辞書としてデータを保存する傾向があり、デフォルトをプロパティリストに保存します。 NSDictionaryオブジェクトは、プロパティリストを使用して簡単に初期化できます。

辞書の使用があなたの好みに合わない場合、デフォルトをプロパティリストに保存し、指定された初期化子でプロパティリストの項目をループし、キーを使用してselfに適用します値コーディング。これは、ユーザーが提供したデータではなく、信頼できるデータにのみ適していることに注意してください。そうしないと、予期しない他のプロパティを設定するためにハイジャックされる可能性があります。

9
Jim

Objective Cには、合成されたプロパティまたはivarを初期化する組み込みのJavaのような方法はありません。ただし、プロパティはほとんど同じに見えるため、それらを作ることを検討する@dynamicそれらを合成する代わりに。

確かに、2つの恐ろしい外観のメソッドを書く必要があります( ここに素敵できれいな例があります あなたのため)=代わりに、プロパティをオブジェクトとしてNSMutableDictionary。これにより、プレーンなivarでは利用できないいくつかの興味深い代替手段が開きます。プロパティが必要になるまでdefer初期化でき、未設定プロパティにデフォルト値を提供できますまたは、キーの値をディクショナリに入力することにより、プロパティ「卸売」を初期化できます。

4
dasblinkenlight

はい、プロパティが初期化される前にデフォルト値を設定する場合にゲッターをオーバーライドできます。

たとえば、.hファイルでプロパティを定義します。

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

.gファイルの実装でゲッターをオーバーライドし、デフォルト値を設定します。

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

上記の辞書の提案は良いものです。私は時々専用の設定オブジェクトを使用しました:

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

@implementation GoalKeepingAttributes
@end

必要に応じて、このクラスには、多数の値とデフォルトを設定するinitメソッドを含めることができます。

これらは単なるプリミティブなので、おそらくCスタイルの構造体も使用できます。

これは単に問題を延期し、初期化を1つのクラスからconfigクラスに移動するだけであることは事実ですが、

  • とにかく辞書でこれを行う必要があります
  • 構成設定をコメントできます
  • 最大の勝利:configクラスは強く型付けされ、コンパイル時にエラーをキャッチし、xcodeコードの補完を可能にします

構成をさまざまなタイプ(Goalkeeping、Technical、Mental)に分割できます。繰り返しますが、それは単に問題を分割しているだけですが、それは物事に集中し続けるのに役立ちます。

0
J.Z.
- (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関数で実行できます。

0
Victor Choy

別の可能性は、プロパティのデフォルトのゲッターをオーバーライドすることです。ゲッターでは、値が初期化されたかどうかを確認し、初期化されていない場合はデフォルト値を返すことができます。 (これは、一部のプロパティタイプでは機能するが、他のプロパティタイプでは機能しないことは明らかです。デフォルト値は、値が設定されていないことを示すものである必要があります。)

0
Joe Dzikiewicz