0

静的な NSMutableArray を持つクラスを作成しました。オーバーライド中に、この配列をクラスの各インスタンスで満たすinit必要があるため、必要以上のコーディングを行う必要はありません。

配列が完全に機能していることを指摘しておく必要があります。正しいデータを保存するのに問題があります。

これは理にかなっていますか?もしそうなら、どうすればこれを行うことができますか?

私はこれをやってみましたが

_instance = self;

[[MyClass getStack] addObject:_instance];

プロパティのインスタンスにアクセスできないようです。ログに記録すると、次のようになります。

2012-07-14 22:37:58.223 Application[4497:1bb03] <MyClass: 0x92cfc70>

さらにコードを編集します。

私の .h ファイル:

@interface MyClass : NSObject

+ (NSMutableArray *)getStack;

私の .m ファイル:

@interface MyClass ()

@end

static NSMutableArray *stack;

@implementation MyClass

クラッシュの画像で編集

配列プロパティをログに記録するNSLog(@"%@", [[[MyClass stack] objectAtIndex:0] adam]);と、その行でクラッシュし、次のエラーが表示されます。

クラッシュエラー

4

4 に答える 4

1

ケビン・グラントの答えは良いですが、問題があります。NSArray は、含まれているオブジェクトを保持します。そのため、インスタンスを配列に追加しても、配列はオブジェクトへの強い参照を維持するため、実際にはオブジェクトの割り当てが解除されることはありません。もちろん、通常は NSArray がその子を保持することは理にかなっており、その下から解放されたオブジェクトへの無効なポインターを保持することはありません。この場合、割り当てが解除される直前に配列からオブジェクトを手動で削除しようとしている場合、実際には、配列に含まれるオブジェクトが保持されないようにする必要があります。

これを行う 1 つの方法は、各インスタンスを NSValue でラップすることです。NSValue には と呼ばれるメソッドがあり-valueWithNonretainedObject:、そのように聞こえます。オブジェクトを含むがそのオブジェクトを保持しない NSValue インスタンスを作成します。これで、NSValue インスタンスを配列に追加すると、配列は含まれているオブジェクトではなく NSValue インスタンスを保持し、インスタンスの割り当て解除を妨げません。コードの例を次に示します。

static NSMutableArray *instanceArray = nil;

@implementation MyClass

+ (void)addInstance:(MyClass *)instance
{
    if (!instanceArray) instanceArray = [[NSMutableArray alloc] init];
    NSValue *value = [NSValue valueWithNonretainedObject:instance];
    [instanceArray addObject:value];
}

+ (void)removeInstance:(MyClass *)instance
{
    NSValue *valueToRemove = nil;
    for (NSValue *value in instanceArray) 
    {
        if ([value nonretainedObjectValue] == instance) 
        {
            valueToRemove = value;
            break;
        }
    }
    if (valueToRemove != nil) [instanceArray removeObject:valueToRemove];
}

- (id)init
{
    self = [super init];
    if (self != nil)
    {
        [[self class] addInstance:self];
    }
 }

 - (void)dealloc
 {
      [[self class] removeInstance:self];
      [super dealloc];
 }

 @end
于 2012-07-14T21:59:14.023 に答える
0

編集:正しく指摘されているように、Objective-C コンテナーには過剰保持の問題があります。また、自動解放プールが利用可能であるとは限らないため、明示的に割り当てる必要があります。

std::set< YourClass* >これらの問題を回避する方法は、動的に再割り当てされた配列や (Objective-C++ の場合)現在のインスタンスへのポインターを含む、まったく保持しないコンテナーを使用することです。

このような「安全な」コンテナが与えられた場合、基本的な考え方は変わりません。通常のイニシャライザがコンテナに追加し (例: myGlobal.insert(self);)、deallocメソッドがコンテナを削除します (例: ) myGlobal.erase(self);

于 2012-07-14T21:42:58.220 に答える
0

init各インスタンスをグローバル配列に追加するのは簡単です:

static NSMutableArray *stack = nil;

@implementation MyClass
+ (void)initialize {
    if (stack == nil)
        stack = [[NSMutableArray alloc] init];
}

+ (id)init {
    self = [super init];
    if (self) {
        [stack addObject:self];
    }
    return self;
}
@end

あなたの問題は何か他のものから来ているに違いありません。グローバル配列を保持していないかのどちらかです。または、「プロパティ」を適切に保存していません (たとえば、保持していません)。か何か。

于 2012-07-15T09:21:12.463 に答える
0

問題は、私が作成したインスタンス プロパティの名前にあることがわかりました。たとえば、'size' の int と 'layer' の CALayer を作成しましたが、これらは標準プロパティによって上書きされていました。それを克服するために、クラス名をプレフィックスとして各プロパティに追加しました。また、形式が %i ではなく %@ であるため、上記のログがクラッシュしていました。助けてくれてありがとう!

于 2012-07-15T12:06:50.880 に答える