2

我通常不会问这样的问题,但我真的无法理解它。我有一个类“GetTableInfoFromDatabase”,它连接到我的数据库并下载一些 JSON。这在我的标签栏应用程序的第一个屏幕上效果很好。我可以尽可能多地调用 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

如果您打算将该变量公开给其他视图控制器,则需要将该变量分配给一个属性。ARC 将并且应该在此代码执行后立即释放getInfo :

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

因此,如果这一行包含在viewDidLoad:中,并且在该方法中没有其他内容引用getInfo,它将立即被释放。为什么,因为你没有告诉编译器它应该保留它。

所以在暴露这个类的视图控制器中,在它可能是一个孩子的任何选项卡上......你会做这样的事情:

视图控制器.h

@class GetTableInfoFromDatabase;  // forward declaration

@interface ViewController : UIViewController

@property (strong, nonatomic) GetTableInfoFromDatabase *getInfo;

视图控制器.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 意味着它将为self.getInfo围绕名为_getInfo的实例变量创建一个 getter 和 setter 。如果您不想将其公开为属性,而只是一个实例变量...您可以这样做:

视图控制器.h

@class GetTableInfoFromDatabase;  // forward declaration

@interface ViewController : UIViewController {
    GetTableInfoFromDatabase _getInfo;
}

视图控制器.m

@implementation ViewController

- (void) viewDidLoad {
    [super viewDidLoad];

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

    [_getInfo getEventDataWithSender:self];
}

默认情况下,除非另有说明,否则编译器将保持对该实例变量的强引用。你也可以有弱引用,所有这些选项都有很好的记录。因此,对于 ARC 或一般的普通旧内存管理,如果您希望它停留一段时间,则需要创建一个实例变量或属性。

老实说... ARC 为您所做的一切就是让您不必调用保留和释放。在 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不会清除请求的委托。您应该将请求保存在 ivar 中,GetTableInfoFromDatabase以便在解除分配时它可以将自己作为委托移除。

附带说明一下,避免在 ObjC 方法前面加上get. 这在 KVC 中有一个特殊的含义(这意味着第一个参数应该通过引用来更新)。通常,您在此处使用的那种方法会以“fetch”开头。

于 2012-10-27T03:23:52.360 回答