2012-04-25 19 views
7

MyClass.hクラスエクステンションで宣言された変数にどのようにアクセスしますか?

@interface MyClass : NSObject 
@end 

MyClass.m

// Define a private variable in a class extension 
@interface MyClass() { 
    NSString *name; 
} 
@end 

その後、後にlldb中:

(lldb) po myClassInstance->name 
error: 'MyClass' does not have a member named 'name' 
error: 1 errors parsing expression 

それでは、どのようにあなたがその変数にアクセスしますデバッガ? Xcodeのに4.3.2

感謝を使用して

答えて

-1

MyClassメソッドの外部からnameにアクセスする必要がある場合は、アクセスするメソッドを定義する必要があります。 (NSString*) name- (void) setName:(NSString*) newNameというメソッドを書くことができますが、プロパティを定義して合成する方が簡単です。

MyClass.hでは、プロパティを定義します。文字列の場合、あなたは通常、それらcopyます

@interface MyClass : NSObject 

@property (copy) NSString* name; 

@end 

MyClass.mで、あなたはまだIVARと、お使いのインタフェースの宣言を使用します。

@interface MyClass() { 
    NSString *name; 
} 
@end 

はしかし、あなたはまた、のsynthesizeに必要あなたの新しい財産。これは名前取得し、設定するためのメソッドを作成:慣例として

@implementation MyClass 

@synthesize name = name; 

@end 

を、IVARの開始または終了時にアンダースコアを置くのが一般的であるので、インタフェースにあなたはNSString *_name;を持っているでしょうし、中あなたは@synthesize name = _nameになります。これは、あなたが不動産を意味するときにivarを誤って使用するのを防ぎます。

あなたは今、あなたの名前プロパティにアクセスすることができます

MyClass me = [[[MyClass alloc] init] autorelease]; 
[me setName:@"My name"]; 
NSLog(@"Name = %@", [me name]); 

Objective-Cのプロパティは、言語の強力な機能ですが、彼らはあなたが学ばなければならないいくつかの癖を持っています。 "objective-C"、 "properties"、 "synthesize"の組み合わせをWeb検索で試してみてください。

まだコンパイラエラーがある場合は、nameにアクセスするコードの部分で質問を編集してください。

+0

OPは、デバッガで変数にアクセスする方法について質問しています。それをコンパイルする方法ではありません。私は同じ問題があります。この回答は役に立ちません。 – rrrus

6

(lldb) po [myClassInstance valueForKey:@"name"]

+0

これはうまく動作しますが、確かに醜い回避策です。 – rrrus

+0

@rrrusええ、それはランタイムを使用しています、それは '@dynamic'プロパティのためにも動作します。 –

+0

あなたが探しているものが象牙であり、財産ではない場合、動作しません。 – AriX

0

きれいに直接これらのインスタンス変数にアクセスする唯一の方法は、有用な機能object_getInstanceVariableを提供するObjective-Cランタイムを介してです。値は参照渡しに渡され、さまざまな型がある可能性があります。そのため、デバッガではあまり役に立ちません。しかしあなたの質問は私に解決策を思いつくよう促しました。

NSObjectにカテゴリを書き込んで、アクセサの副作用を心配することなく、デバッガからインスタンス変数をイントロスペクトすることができます。

(lldb) po [self valueOfInstanceVariable:@"_name"] 
IMG_4078.PNG 

ここでは、コードです:

NSObjectの+ IvarIntrospection.h

#if DEBUG 
#import <Foundation/Foundation.h> 

@interface NSObject (IvarIntrospection) 

- (id)valueOfInstanceVariable:(NSString *)ivarName; 

@end 

#endif 

NSObjectの+ IvarIntrospection.m

#if DEBUG 
#import "NSObject+IvarIntrospection.h" 
#import <objc/runtime.h> 

@implementation NSObject (IvarIntrospection) 

- (id)valueOfInstanceVariable:(NSString *)ivarName { 
    // Get the value of the instance variable 
    // Use a union in order to convert the value to a float or double (see http://en.wikipedia.org/wiki/Type_punning) 
    union { 
     void *value; 
     float f; 
     double d; 
    } ivar; 
    Ivar ivarInfo = object_getInstanceVariable(self, [ivarName UTF8String], &ivar.value); 

    // If the instance variable doesn't exist, try adding an underscore 
    if (!ivarInfo && ![ivarName hasPrefix:@"_"]) { 
     NSString *underscoredIvarName = [@"_" stringByAppendingString:ivarName]; 
     NSLog(@"Instance variable '%@' does not exist. Perhaps you meant '%@?' Let's try that.", ivarName, underscoredIvarName); 

     return [self valueOfInstanceVariable:underscoredIvarName]; 

    // If there's already an underscore, error 
    } else if (!ivarInfo) { 
     NSLog(@"Instance variable '%@' does not exist.", ivarName); 
     return nil; 
    } 

    // Figure out what type the instance variable is and return a sensible representation 
    const char *type = ivar_getTypeEncoding(ivarInfo); 
    switch (type[0]) { 
     case 'c': 
      return [NSNumber numberWithChar:(char)ivar.value]; 
     case 'i': 
      return [NSNumber numberWithInt:(int)ivar.value]; 
     case 's': 
      return [NSNumber numberWithShort:(short)ivar.value]; 
     case 'l': 
      return [NSNumber numberWithLong:(long)ivar.value]; 
     case 'q': 
      return [NSNumber numberWithLongLong:(long long)ivar.value]; 
     case 'C': 
      return [NSNumber numberWithUnsignedChar:(unsigned char)ivar.value]; 
     case 'I': 
      return [NSNumber numberWithUnsignedInt:(unsigned int)ivar.value]; 
     case 'S': 
      return [NSNumber numberWithUnsignedShort:(unsigned short)ivar.value]; 
     case 'L': 
      return [NSNumber numberWithUnsignedLong:(unsigned long)ivar.value]; 
     case 'Q': 
      return [NSNumber numberWithUnsignedLongLong:(unsigned long long)ivar.value]; 
     case 'f': 
      return [NSNumber numberWithFloat:ivar.f]; 
     case 'd': 
      return [NSNumber numberWithDouble:ivar.d]; 
     case '*': 
      return [NSString stringWithUTF8String:(const char *)ivar.value]; 
     case '@': 
     case '#': 
      return (id)ivar.value; 
     case ':': 
      return NSStringFromSelector((SEL)ivar.value); 
     default: 
      return [NSValue valueWithBytes:&ivar.value objCType:type]; 
    } 
} 

@end 

#endif 
プロジェクトにカテゴリを追加した後、あなたはこれを行うことができます

リリース用にコンパイルすると、カテゴリは自動的に無効になります(debu gマクロ)。

+0

これをNSObjectのカテゴリにしたいのであればOKですが、それはデバッガのいくつかの値を見て少し重いようです... –

+0

母、もう一度やります。私があなたの答えにコメントしたとき、私はそれがかなり重くなってしまうとは思わなかった。私は間違っている!しかし、 "インスタンス変数に直接アクセスするにはどうすればいいですか"という疑問に対する正確な答えです.Cocoa開発を行うときには便利だと思います。インスタンス変数が設定されていない場合は、まだ。 – AriX

+1

最初のバージョンは4行でしたが、Objective-C以外のタイプではうまくいかなかったことに気がついたとき、私はちょっと離れました... – AriX

関連する問題