2012-06-29 50 views
2

我是objective-c(以及Apple的所有事情)的新手。在不同的类中释放/访问同一个名字的不同对象

我在设计一个iOS应用程序,并遇到了一个对我来说很有趣的bug。基本上,我开始在一个VC(LoginViewController)中,并沿着我将另一个VC推到我的导航控制器(MyProfileViewController)的方式。

但是当我通过堆栈回到LoginViewController时,触摸屏幕上的任何对象都会导致出现EXEC_BAD_ACCESS错误。在一些头部划伤之后,我决定改变视图中的表名(我的两个ViewControllers都包含一个UITableView,在他们各自的.m文件中定义,并且我将这两个命名为'myTable')。

事实证明,对于我的应用程序来说,除了导致可读性差(您不必在这一点上反对我),将两个表命名为导致崩溃的原因相同。所以我想,当MyProfileViewController被释放时,它从LoginViewController释放'myTable'以及?

有了正常的错误,我意识到自己的错误,试着从中学习,然后继续前进。但是这对我而言并没有意义,为什么它首先会造成崩溃。任何见解?作为参考,下面是我在两个ViewController中定义和释放UITableView的方法。

@implementation MyProfileViewController//same format as LoginViewController 

UITableView* myTable;//It's since been renamed to something more descriptive 

//code... 

-(void)viewDidLoad{ 
    [super viewDidLoad]; 
    myTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStyleGrouped]; 
    [myUpdateTable setDataSource:self]; 
    [myTable setDelegate:self]; 
    [self.view addSubview:myTable]; 
} 

//code... 

-(void)dealloc{ 
    [myTable release]; 
    [super dealloc]; 
} 
+0

理想情况下,这不应该发生。你可以尝试一件事。在释放表之前选择相同的名称并在dealloc中,首先编写这两行代码 - tableView.delegate = nil; tableView.datasource = nil; – rishi

+0

这里一定还有别的事情要做。这些名称只在其范围内有效,在这种情况下仅为自己的对象。在'LoginViewController'的'viewDidUnload'中有什么有趣的事情发生? –

+0

嗯。 @rishi我试着在dealloc中设置委托和数据源为零,但它没有影响任何东西。 Phillip Mills我认为这可能是一个很好的检查位置,所以我评论了一切,但[超级viewDidUnload],它仍然在发生。这很奇怪。 – user1080952

回答

2

首先,做我正确地读你的代码,你UITableView没有在@interface界定?如果是这样,你已经定义了myTable是一个全局变量。这不是一个好主意,尽管如果你在两个.m文件中使用了相同的全局变量,链接器并没有抱怨,但我很惊讶(但它肯定会解释为什么使用相同的名称会导致问题)。你真的想让你的UITableView成为一个实例变量。你可以在你的.m文件的顶部定义私有实例变量如下(@implementation之前把这个):

@interface MyProfileViewController() 
{ 
    UITableView* _myTable; 
} 
@end 

如果你这样做的话,那不要紧,无论您的实例变量的名字在一个班级碰巧和另一个班级里的人员一样。类实例变量的作用域限于该类。 (顺便说一句,作为一种风格问题,很多人在他们的类实例变量前面加上下划线,通常是将它们与类属性和局部变量区分开。)

其次(和你原来的问题无关)建议在viewDidLoad释放,从而:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    _myTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStyleGrouped]; 
    [_myTable setDataSource:self]; 
    [_myTable setDelegate:self]; 
    [self.view addSubview:_myTable]; 
    [_myTable release]; 
} 

(而且,很明显,从dealloc删除release声明。)

没有理由推迟release:当你分配/初始化,它有一个保留计数+1,当你addSubview它获得+2的保留计数,并且当你释放时,你只需将释放计数返回+1(意味着它不会被交易,因为self.view正在保留它,但当视图最终释放它时,你的tableview将会为你自动处理)。但是,不是推迟它(如果在推送到新视图控制器后得到didReceiveMemoryWarning),那么原始代码将会泄漏。

如果您使用ARC,通常会为您清理这种愚蠢的内存管理问题,但由于您未使用ARC,因此可能需要调整发布的位置。

+0

创建它作为一个实例变量做了诀窍,现在我可以让它们成为相同的名称(无论如何,为了便于阅读,现在重命名表)。我计划在下一个项目中使用ARC,但作为初学者,我希望在使用其新功能之前尽可能多地了解objective-c中的内存管理。 – user1080952

+0

做得很好。我只是在接口中看到变量,我甚至在不存在的情况下阅读它。 :) –

相关问题