0

ビューコントローラーにテーブルビューを表示させました。以下を参照してください。

//.h file
@interface CoreDataViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
    //NSArray property
    @property (retain, nonatomic) NSArray *arr;
@end

//.m file
- (void)viewDidLoad {
    //fetch data from core data, pass to arr property
    //context is a instance of NSManagedObjectContext
    arr = [context executeFetchRequest:request error:nil];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {   
    if (arr == nil) {
        return 0;
    }
    return [arr count]; //program stop here, nothing showed up in output console
}

xcode Profile(Instrument) は、リターン [arr count] にゾンビ オブジェクトがあることを示しています。 おそらくバックグラウンドで何が起こったのか混乱していますが、プロパティはiOSによってリリースされる可能性がありますが、プロパティには.hファイルに保持キーワードがあります。

NSArray を次のように NSMutableArray に置き換えると、この問題を解決できるソリューションが見つかります。

@interface CoreDataViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
    //change to NSMutableArray
    @property (retain, nonatomic) NSMutableArray *arr;
@end

- (void)viewDidLoad {
    //convert NSArray to NSMutableArray
    arr = [[context executeFetchRequest:request error:nil] mutableCopy];
}

mutableCopyメソッドに保持または自動解放はありますか?

4

3 に答える 3

0

はい、プロパティarr do には .h ファイルに保持キーワードがありますが、ivar を直接使用し、セッター メソッドを使用してarrの値を設定しませんでした。したがって、 arrの保持カウントは増加しません。コードを次のように変更する必要があります。

//.m file
- (void)viewDidLoad {
  //fetch data from core data, pass to arr property
  //context is a instance of NSManagedObjectContext
  self.arr = [context executeFetchRequest:request error:nil];
}

そして、dealloc メソッドでarrを解放します

- (void)dealloc
{
  [arr release];
  [super dealloc];
}

NSArray を NSMutableArray に変更する必要はありません

于 2012-04-25T06:28:37.113 に答える
0

Basic Memory Management Rulesに従って、はい、 mutableCopyは保持カウントを増やします。allocつまり、名前が、newcopy、またはすべてで始まるメソッドは、mutableCopy保持カウントが +1 のオブジェクトを返します (つまり、オブジェクトは保持されるため、所有権を取得することになり、ARC 以外のプロジェクトでは、手動でリリースする責任があります)。このexecuteFetchRequestメソッドはそうではないので、0 の保持カウントを返す (可能性がある) ため、所有権を取得しない限り、その存在を信頼することはできません。

明らかに、プロパティを保持プロパティとして定義したため、保持されると想定していました。ただし、それを行うにはシステム生成のセッターを使用する必要がありますが、最初のコード サンプルではそれを行いません。むしろ、セッターをバイパスして ivar に直接アクセスしています。所有権を取得したい場合は、プロパティによって暗示されている保持カウントを増やして、デフォルトのセッターを呼び出す必要があります。

[self setArr:[context executeFetchRequest:request error:nil]];

または同等のドット表記を使用します。

self.arr = [context executeFetchRequest:request error:nil];

しかし、ivar arr を単独で (ドットやself setArr構文なしで) 使用すると、setter メソッドがバイパスされます。必要な保持を行っていないため、これは良い習慣ではありません。この例では (arr にはまだ値がないことがわかっているため)、理論的には次のようにすることができます。

arr = [[context executeFetchRequest:request error:nil] retain];

しかし、 arr が既に別の配列へのポインタを持っている可能性がある場合は、次のようにします。

[release arr];
arr = [[context executeFetchRequest:request error:nil] retain];

セッターを使用するのは安全であり、このばかげたことを避けることができます。Declared Propertiesを見て、 の使用がretainどのセッター コードにどのように変換されるかを理解してください。

アップデート:

ちなみに、他の人が指摘しているように、上記のコードは配列が保持されないという問題を解決しますが、保持に成功したら、dealloc でそれを解放することを忘れないでください。

于 2012-04-25T06:32:41.533 に答える
0

mutableCopy を使用している場合は、自分で変数を解放する必要があります。保持カウントが 1 増加しますが、減少しません。次のように使用できるかもしれません-

arr = [[[context executeFetchRequest:request error:nil] mutableCopy] autorelease];
于 2012-04-25T05:02:50.337 に答える