我通常不会问这样的问题,但我真的不能理解它。我有一个类'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'之前已经由最后一次初始化它的类初始化之前。仍然崩溃。
有没有人有任何想法?这太令人沮丧了!
答案 0 :(得分:10)
如果您打算将该变量公开给其他视图控制器,则需要将该变量分配给属性。在此代码执行后,ARC将,并且应该立即解除分配 getInfo :
GetTableInfoFromDatabase *getInfo = [[GetTableInfoFromDatabase alloc]init];
[getInfo getEventDataWithSender:self];
因此,如果该行包含在 viewDidLoad:中,并且该方法中没有其他任何内容引用 getInfo ,则会立即释放该行。为什么,因为你没有告诉编译器它应该保留它。
所以在暴露这个类的视图控制器中,在任何标签上它可能是...的孩子......你会做这样的事情:
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];
}
因此,当您在标题中将属性声明为强时,它将保留对它的强引用。 @Synthesize getInfo = _getInfo意味着它将为名为 _getInfo 的实例变量周围的 self.getInfo 创建一个getter和setter。如果您不想将其作为属性公开,只需要一个实例变量......您可以这样做:
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为你做的就是让你不必打电话给保留和释放。在ARC之前,设置该属性将如下所示:
GetTableInfoFromDatabase getInfo = [[GetTableInfoFromDatabase alloc]init];
self.getInfo = getInfo;
[getInfo release];
现在使用ARC,编译器只是为您编写代码;)希望这有帮助!
[self.getInfo getEventDataWithSender:self];
答案 1 :(得分:0)
您的GetTableInfoFromDatabase
对象正在被取消分配,几乎可以肯定,因为没有任何东西可以强烈引用它。在上面的代码中,getInfo
是一个局部变量,所以我希望它会在此代码之后很快发布,除非你将它存储在某个地方。
几乎可以肯定,dealloc
中的GetTableInfoFromDatabase
不会清除请求的委托。您应该在GetTableInfoFromDatabase
的ivar中保存请求,以便在取消分配时将其作为委托删除。
作为旁注,请避免使用get
添加ObjC方法。这在KVC中具有特殊含义(这意味着第一个参数应该通过引用更新)。通常,您在此处使用的方法将以“fetch”开头。