0

私は 2 日間壁に頭をぶつけて、自分のコードの何が問題なのかを突き止めようとしています。これまでのところ、何もありません。私が発見した唯一のことは、オブジェクトがそれ自体で release を呼び出そうとしていて、まだインスタンス化されていないという事実です。(ただし、何らかの理由で100%発生するわけではありません。考えているときだけです)

問題を説明させてください(何かを見落としているかもしれません。皆さんが私の闇に光を当ててくれることを願っています)

私のモデルオブジェクト

Person {
  NSString *name;
  NSNumber *age;
}

@property(nonatomic, retain) NSNumber* TheAge;
@property(nonatomic, retain) NSString *TheName;

私の実装

@synthesize TheName = name;
@synthesize TheAge = age;

+(Person*)personFromDictionary:(NSDictionary*)dic {
  Person* newPerson = [[[Person alloc] init]autorelease];
  newPerson.theAge = [dic objectForKey:kAge];
  newPerson.theName = [dic objectForKey:kName];

  return newPerson;
}

-(void)dealloc {
  self.TheAge = nil;
  self.TheName = nil;
}

サーバーからJSON配列を読み取り、ダウンロードして辞書に解析する「コレクタースレッド」があります。ディクショナリのすべてのエントリは人物オブジェクトに対応します。このスレッドは、単に Person モデルを使用した別のクラスです。

スレッドはこのようなことをします (自動解放プールで)

NSDictionary *parsedDict = download.returnValue;

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Person *tmpPerson = personFromDictionary

[entryDictionary setObject:tmpPerson forKey:kAge];

[pool release];

[self updateEntries:entryDictionary];

-(void)updateEntries:(NSMutableDictionary*)updatedDict {
   NSArray *keys = [updatedDict allKeys];
   for(NSString *key in allKeys){
        Person *entry = [updatedDict valueForKey:key];
        [entriesLock lock];
        [currentPersonEntries setObject:entry forKey:key];
        [entriesLock unlock];

    }
}

クラッシュが発生すると(何らかの理由でランダムに発生し、次のようにスタックトレースが取得されます

人の割り当て解除

person setTheAge (バム クラッシュ)

セッターはこんな感じになると思います

-(void)setTheAge:(NSString*)theAge {
  [theAge retain];
  [age release]; // it doesn't exist for some reason???
  age = theAge;
}

この種のものに対してどのように保護できますか?

4

1 に答える 1

2

いくつかの考え。

まず、次のものがあります。

Person {
    NSString *name;
    NSNumber *age;
}

@property(nonatomic, retain) NSNumber* TheAge;
@property(nonatomic, retain) NSString *TheName;

そして、実装には次のものがあります。

@synthesize TheName = name;
@synthesize TheAge = age;

Apple は、ivar を明示的に定義することを推奨しなくなりましたが、synthesize ステートメントに任せてください (おそらく、それらのいずれかのスペルを間違えると、余分な意図しない ivar が作成される可能性があるためです)。したがって、次のことが必要になる場合があります。

@interface Person : NSObject

@property(nonatomic, retain) NSNumber* theAge;
@property(nonatomic, retain) NSString* theName;

@end

また、ivar に名前を付ける場合、新たな標準は (ただし、もちろん、あなたが望むことを行うことができます) ivar にアンダースコアを使用し、変数名を小文字で開始することです... クラスでは大文字、変数では小文字、たとえば:

@synthesize theName = _theName;
@synthesize theAge = _theAge;

第二に、deallocあなたはそれらの ivar を nil に設定しています。これは ARC コードでリリースする正しい方法ですが、ARC 以外のコードでは、単に ivar を使用し、リリース コマンドを使用する必要があります。

- (void)dealloc {
    [_theAge release];
    [_theName release];

    [super dealloc];
}

第三に、そのセッターを書いていsetTheAgeますか、それともコンパイラーが何をしているのかを推測していますか? あなたのコードはおそらく改善される可能性があります (プロパティと同じローカル変数を使用しているため、混乱するだけです。キー値の通知を行う必要があるなど)。他に達成しようとしていることがない限り、コンパイラに独自のセッターを実行させる方がよいでしょう。お知らせ下さい。

第四に、あなた-(Person*)personFromDictionary:(NSDictionary*)dicは興味深い方法です。次のように、独自の init を作成することをお勧めします。

- (Person*)initFromDictionary:(NSDictionary*) dic 
{
    self = [super init]; // I always inherit from NSObject, in which case you'd have this line

    if (self)
    {
        self.theAge  = [dic objectForKey:kAge];
        self.theName = [dic objectForKey:kName];
    }

    return self;
}

このようにして、次のように Person オブジェクトを作成できます。

Person *aPerson = [[Person alloc] initWithDictionary:entryDictionary];

現在の実装では、Personオブジェクトが既に存在すると想定していますが (メソッド名の前に「+」ではなく「-」を付けているため)、新しいオブジェクトを作成します。ちょっと変です。あなたはそのようなことをすることができるかもしれませんが、上記のコードパターンはより一般的であり、あなたが望むものを達成します.

最後に、あなたが何をしようとしているupdateEntriesのかわからないので、そこに何を提案すればupdateEntriesよいのかわかりませんが、プールの外側を完全に理解していません.人物オブジェクトなど。そこで何を達成しようとしているのかを説明していただければ、それについても喜んで 2 セント差し上げます。

アップデート:

ところで、コードをデバッグしている場合は、NSLogステートメントを追加すると役立つことがあります。ただし、それを容易にするためdescriptionにクラスのメソッドを作成することをお勧めします。これにより、オブジェクトの内容を確認できます。たとえば、次のようになります。PersonPerson

- (NSString *)description
{
    return [NSString stringWithFormat:@"Person (%p) {\n  theName = '%@'\n  theAge = %@\n}", self, self.theName, self.theAge];
}

このようにしてPerson、たとえば、という名前のオブジェクトがある場合aRandomPerson、次のようなステートメントを作成できます。

NSLog(@"%@", aRandomPerson);

また、オブジェクトを含むディクショナリ エントリがあるPerson場合、NSLogそのディクショナリを使用すると、意味のあるログ ステートメントが得られます。これは、アイテムの内容を診断するのに役立ちます(オブジェクトだけではなく、NSDictionary実際にオブジェクトが含まれている場合)。PersonNSStringNSNumber

于 2012-06-25T19:20:57.077 に答える