2

普段はこういう質問はしないのですが、どうしても頭に入ってしまいます。データベースに接続してJSONをダウンロードするクラス「GetTableInfoFromDatabase」があります。これは、タブバー アプリケーションの最初の画面からうまく機能します。データを効果的に更新したいだけ、getNewData メソッドを呼び出すことができます。

「GetTableInfoFromDatabase」クラスのインスタンスを作成して、別のタブからまったく同じメソッドを呼び出そうとすると、問題が発生します。次のエラーが表示されます。

*** -[GetTableInfoFromDatabase respondsToSelector:]: message sent to deallocated instance 0x1d89e830

面白いことに、私は ARC を使用しています。(私の意見では) 犯人は ASIHTTPRequest です。プロジェクトをコンパイルするには、-fno-objc-arc を有効にする必要がありました。このライブラリは GetTableInfoFromDatabase クラスで使用されます。

クラスは次のとおりです。

- (void) getEventDataWithSender:(id)sender{


ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"-------.com/getdata.php"]];
[request setDelegate:self];
NSLog(@"Running!");
[request startAsynchronous];
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = appDelegate.managedObjectContext;
}

そして、これが私がそれを呼んでいる方法です:

GetTableInfoFromDatabase *getInfo = [[GetTableInfoFromDatabase alloc]init];
[getInfo getEventDataWithSender:self];

タブの順序も変更したので、表示される最初のタブは純粋にこのメソッドを呼び出すだけで、他には何もありません。「GetTableInfoFromDatabase」が前回最初に初期化したクラスによって以前に初期化される前でさえありません。それでもクラッシュします。

誰かアイデアはありますか?これはとてもイライラします!

4

2 に答える 2

10

他のView Controllerに公開する予定がある場合は、その変数をプロパティに割り当てる必要があります。このコードが実行された後、ARC はすぐにgetInfoの割り当てを解除します。

GetTableInfoFromDatabase *getInfo = [[GetTableInfoFromDatabase alloc]init];
[getInfo getEventDataWithSender:self];

したがって、この行がたとえばviewDidLoad:に含まれていて、そのメソッドでgetInfoを参照するものが他にない場合は、すぐに解放されます。なぜ、それを保持する必要があることをコンパイラに伝えていないからです。

したがって、このクラスを公開しているView Controllerで、それが子である可能性のあるタブで...次のようにします:

ViewController.h

@class GetTableInfoFromDatabase;  // forward declaration

@interface ViewController : UIViewController

@property (strong, nonatomic) GetTableInfoFromDatabase *getInfo;

ViewController.m

@implementation ViewController

@synthesize getInfo = _getInfo;

- (void) viewDidLoad {
    [super viewDidLoad];

    self.getInfo = [[GetTableInfoFromDatabase alloc]init]; // assign your value to a property

    [self.getInfo getEventDataWithSender:self];
}

したがって、ヘッダーでプロパティをStrongとして宣言すると、それへの強い参照が維持されます。@Synthesize getInfo = _getInfo は、 _getInfo という名前のインスタンス変数の周りに self.getInfo のゲッターとセッターを作成することを意味ます。プロパティとして公開したくない場合は、単にインスタンス変数として公開します...これを行うことができます:

ViewController.h

@class GetTableInfoFromDatabase;  // forward declaration

@interface ViewController : UIViewController {
    GetTableInfoFromDatabase _getInfo;
}

ViewController.m

@implementation ViewController

- (void) viewDidLoad {
    [super viewDidLoad];

    _getInfo = [[GetTableInfoFromDatabase alloc]init]; // assign your value to a property

    [_getInfo getEventDataWithSender:self];
}

デフォルトでは、特に指定がない限り、コンパイラはそのインスタンス変数への強い参照を維持します。弱参照も使用できます。これらのオプションはすべて、十分に文書化されています。したがって、ARC、または一般的な昔ながらのメモリ管理では、しばらくぶらぶらしたい場合は、インスタンス変数またはプロパティを作成する必要があります。

正直なところ... ARCがあなたのためにしているのは、retainとreleaseを呼び出さなくても済むようにすることだけです。ARC の前は、そのプロパティの設定は次のようになっていました。

    GetTableInfoFromDatabase getInfo = [[GetTableInfoFromDatabase alloc]init];

    self.getInfo = getInfo;

    [getInfo release];

ARC を使用すると、コンパイラがそのコードを作成するだけです ;) これがお役に立てば幸いです!

    [self.getInfo getEventDataWithSender:self];
于 2012-10-27T03:25:52.423 に答える
0

オブジェクトGetTableInfoFromDatabaseへの強い参照を保持しているものがないため、オブジェクトの割り当てが解除されていることはほぼ確実です。上記のコードでgetInfoは、はローカル変数なので、どこかに保存していない限り、このコードの直後に解放されると思います。

ほとんどの場合、あなたのdeallocinGetTableInfoFromDatabaseはリクエストのデリゲートをクリアしません。GetTableInfoFromDatabase割り当てが解除されたときにデリゲートとして自分自身を削除できるように、リクエストを ivar に保持する必要があります。

補足として、ObjC メソッドの前にget. これは、KVC では特別な意味を持ちます (最初のパラメーターが参照によって更新されることになっていることを意味します)。通常、ここにある種類のメソッドは「fetch」で始まります。

于 2012-10-27T03:23:52.360 に答える