2013-08-06 9 views
5

ivarsを宣言せずにスーパークラスに@propertyを宣言しただけでサブクラス化し、サブクラスでスーパークラスivar(_propertyName)を使用してgetterを実装しようとすると、xcodeはUse of undeclared identifier '_propertyName'というエラーを呼び出します。スーパークラスでivarsを宣言するか、サブクラスで@synthesizeを宣言しますか?

ベストプラクティスに準拠したソリューションは何ですか?

万一Iサブクラスの@implementationまたは

@synthesize propertyName = _propertyName
@interface SuperClass : AnotherClass 
{ 
    Type *_propertyName; 
} 

@property Type *propertyName; 

@end 

編集:私はによる自動プロパティのアクセサメソッドの「合成」と 『アンダーバーアイバーズ』の作成を理解して
コンパイラ。
イバールはSuperClassの実装からアクセスできません。@synthesizeまたはインターフェイスまたは実装セクションにivarsが宣言されていません。私の例

さらに明確化: 免責事項:アルフィーハンセン

@interface SuperViewController : UIViewController 
@property (nonatomic, strong) UITableView * tableView; // ivar _tableView is automatically @synthesized 
@end 

#import "SuperViewController.h" 

@interface SubViewController : SuperViewController 
// Empty 
@end 

@implementation SubViewController 

- (void)viewDidLoad 
{ 
    NSLog(@"tableView: %@", self.tableView); // this is perfectly OK 
} 

// ************* This causes problem ************** 
- (UITableView *) tableView { 
    if (!_tableView) { // Xcode error: Use of undeclared identifier '_propertyName' 
     _tableView = [[SubclassOfUITableView alloc] init]; 
    } 
    return _tableView; 
} 
// ************************************************ 


@end 
+0

これは奇妙です。Objective Cのivarsはデフォルトで保護されているため、サブクラスは自分のものと同じようにアクセスできなければなりません。どのように '_propertyName'にアクセスしてそのエラーを取得しますか? – dasblinkenlight

+4

あなたのプロパティが '@property Type * _propertyName;'ならば、ivarは '__propertyName'と思うでしょう。 (2つのアンダースコア)あなたのサブクラスがivarに直接アクセスする必要があるのはなぜですか? – BergQuester

+0

FYI、プロパティを@合成する必要はもうありません。ヘッダファイルでそれらを宣言するだけで、合成はXcode /コンパイラによって自動的に行われます。 – davidf2281

答えて

7

スーパークラスとサブクラスの両方でivarを使用する場合は、両方の実装に含まれている唯一のファイルであるため、スーパークラスのインタフェースで宣言する必要があります。さもないと、スーパークラスの実装に何があるのか​​を推測しようとしているだけで、xcodeはゲームをプレイしません。

上記は、そのivarを使用するかどうかにかかわらず、trueです。あなたはスーパークラスでプロパティを持っていて、サブクラス実装で書く場合

は今:

@synthesize propertyName = _propertyName 

あなただけのスーパーにあった、あなたが好きなそのプロパティの実装あなたが捨てていることを言っていますxcodeで生成された標準のセッターとゲッター、_propertynameという名前のivarで作業しています。多分、スーパークラスは同じ方法で動作します。

0

これからのコードのブロックを盗まれた内容は、うまく動作するはずです。 self.tableView_tableViewは、両方ともSubViewControllerからアクセス可能である必要があります。

@interface SuperViewController : UIViewController 
@property (nonatomic, strong) UITableView * tableView; // ivar _tableView is automatically @synthesized 
@end 

#import "SuperViewController.h" 

@interface SubViewController : SuperViewController 
// Empty 
@end 

@implementation SubViewController 

- (void)viewDidLoad 
{ 
    NSLog(@"tableView: %@", self.tableView); 
} 

@end 

編集: オーケー、今私はあなたが疑問方がよいでしょう理解しています。このquestionをチェックしてください。重複のように見えて、あなたの質問に答えているようです。私。インスタンス変数を明示的に定義する必要があるようです。

+0

さて、このメソッドをSubViewController実装に追加した場合はどうなりますか? - (UITableView *)tableView { if(!_tableView){ _tableView = [[SubclassOfUITableView alloc] init]; } return _tableView; } – user2626382

+0

"ivar _tableViewは自動的に\ @合成されます"どのようにそれを知っていますか? mファイルに\ @synthesizeがなく、ゲッターやセッターのカスタム実装がないと仮定しています。それをどうやって知ることができますか? – Nicolas

+0

ケースが反対であるため、その質問の複製ではありません。スーパークラスはsetterのみを実装しており、プロパティは 'readwrite'であるため、スーパークラスの実装から簡単にアクセスできますので、私はivarを必要とします。 – user2626382

0

この場合、明らかにivarの自動合成は機能しません。次のコードはコンパイラエラー "宣言されていない識別子の使用_x"で失敗しますが、JFNBclassでのみ使用できます。 ivar宣言のコメントを外し、コンパイラのエラーが消えます。デフォルトの合成では、継承しているクラスから見える_xを作成していないようです。

JFNAclass.h

#import <Foundation/Foundation.h> 

@interface JFNAclass : NSObject { 
    // NSNumber *_x; 
} 

@property NSNumber *x; 
- (NSNumber *) xTest; 

@end 

JFNAclass。M

#import "JFNAclass.h" 

@implementation JFNAclass 

- (NSNumber *) xTest 
{ 
    return _x; 
} 

@end 

JFNBclass.h

#import <Foundation/Foundation.h> 
#import "JFNAclass.h" 

@interface JFNBclass : JFNAclass 

- (void) printIt; 
- (void) setIt; 

@end 

JFNBclass.m

#import "JFNBclass.h" 

@implementation JFNBclass 

- (void) setIt 
{ 
    _x = [[NSNumber alloc] initWithInt:2]; 
} 

- (void) printIt 
{ 
    NSLog(@"_x is %@", _x); 
} 

@end 
@synthesize
+1

[合成されたインスタンス変数の可視性は何ですか?](http://stackoverflow.com/q/8510464) –

+0

私はそのテストを実行しませんでした... ...結果はSOと完全に一致しています参照してください。クェレ驚き!だから私はその答えを否定した。 – Fred

+0

これを書き留める時間を取ってくれてうれしいです。ほとんど同じコードが書き留めました。しかし、慎重に読んだら、私はタイトルの中にこの解決法を述べていました。 – user2626382

0

によって作成アイバーズは@privateあります。 (これは、両方の明示的な@synthesize文と自動合成のために真である。)

あなたのクラスSuperViewControllerはIVAR _tableViewを持っているが、それはそう、あなたのサブクラスがそれを使用することはできません@privateです。サブクラスで使用できるivarが必要な場合は、ivarを明示的に宣言して@private以外のものにする必要があります。 (@synthesize tableView=_tableViewを使用して、宣言されたivarを使用するようにしてください。)

0

ivarには全くアクセスしません。 getterをオーバーライドしたいので、superを呼び出してください。

- (UITableView *)tableView { 
    UITableView *tableView = [super tableView]; 
    if (! tableView) { 
     tableView = [[SubclassOfUITableView alloc] init]; 
     self.tableView = tableView; 
    } 
    return tableView; 
} 
+0

おそらくもっとコードを提供したはずです。私の場合と同様に、 '[super tableView]'は '(UITableView *)'( 'alloc'edと' init'ed)を返すでしょう - 'nil'ではなく - サブクラスのゲッターは' SubclassOfUITableView'を返しません。 – user2626382

+0

まだ、私はivarに全くアクセスしません。**両方のゲッターが怠惰で、 'UITableView'の別のクラスを返す場合、createメソッド' - (Class)tableViewClass'がそれをオーバーライドします。常に良い解決策があります。 – Tricertops

関連する問題