2

我是objective-c的新手(以及苹果的所有东西,就此而言)。

我正在设计一个 iOS 应用程序并遇到了一个对我来说似乎很有趣的错误。基本上,我从一个 VC (LoginViewController) 开始,在此过程中我会将另一个 VC 推送到我的导航控制器 (MyProfileViewController) 上。

但是当我通过堆栈返回 LoginViewController 时,触摸屏幕上的任何对象都会导致EXEC_BAD_ACCESS错误。经过一番摸索,我决定更改视图中的表名(我的两个 ViewController 都包含一个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];
}
4

1 回答 1

2

首先,我是否正确阅读了您的代码,您的代码UITableView中没有定义@interface?如果是这样,则您已定义myTable为全局变量。这不是一个好主意,虽然我很惊讶如果您在两个 .m 文件中使用相同的全局变量,链接器没有抱怨(但它肯定会解释为什么使用相同的名称会导致问题)。你真的希望你UITableView成为一个实例变量。您可以在 .m 文件的顶部定义私有实例变量,如下所示(将其放在 .m 之前@implementation):

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

如果你这样做,那么一个类中的实例变量的名称是否恰好与另一个类中的相同并不重要。类实例变量的范围仅限于该类。(顺便说一句,作为一种风格,许多人在他们的类实例变量前加上下划线,通常是为了将它们与类属性和局部变量区分开来。)

第二个(与您最初的问题无关),我建议发布 in 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];
}

(而且,显然,release从您的 . 中删除该声明dealloc。)

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

如果您使用 ARC,通常会为您清理这种愚蠢的内存管理问题,但鉴于您没有使用 ARC,您可能需要调整释放位置。

于 2012-06-29T16:41:02.523 回答