释放/访问不同类中同名的不同对象 [英] Releasing/accessing different objects of the same name in different classes

查看:27
本文介绍了释放/访问不同类中同名的不同对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Objective-c(以及 Apple 的所有东西,就此而言)的新手.

I'm a newbie to objective-c (and all things Apple, for that matter).

我正在设计一个 iOS 应用程序,但遇到了一个我觉得很有趣的错误.基本上,我是从 VC (LoginViewController) 开始的,在此过程中,我会将另一个 VC 推送到我的导航控制器 (MyProfileViewController).

I'm designing an iOS app and ran into a bug that seemed pretty interesting to me. Basically, I started out in a VC (LoginViewController), and somewhere along the the way I would push another VC onto my navigation controller (MyProfileViewController).

但是当我通过堆栈返回到 LoginViewController 时,触摸屏幕上的任何对象都会导致 EXEC_BAD_ACCESS 错误.经过一番摸索,我决定更改视图中的表名(我的两个 ViewController 都包含一个 UITableView,在它们各自的 .m 文件中定义,并且我都将它们命名为myTable").

But when I backed my way through the stack back to LoginViewController, touching any object on the screen would cause an EXEC_BAD_ACCESS error. After some head scratching, I decided to change the table names in the views (both of my ViewControllers contained a UITableView, defined in their respective .m files, and both of which I named 'myTable').

事实证明,对于我的应用程序,除了导致可读性差(您不必在这一点上责备我)之外,将两个表命名为相同的名称也是导致崩溃的原因.所以我猜当 MyProfileViewController 被释放时,它也从 LoginViewController 中释放了myTable"???

It turned out that for my app, aside from contributing to poor readability (you don't have to berate me on this point), naming both of the tables the same was what was causing the crash. So I guess that when MyProfileViewController was being deallocated, it released 'myTable' from LoginViewController as well???

对于正常的错误,我意识到我的错误,尝试从中学习,然后继续前进.但这对我来说是没有意义的,为什么它首先会造成崩溃.任何见解?作为参考,以下是我在两个 ViewController 中定义和发布 UITableView 的方式.

With normal bugs, I realize my error, try to learn from it, and move on. But this just doesn't make sense to me as to why it's creating a crash in the first place. Any insights? For reference, here's how I was defining and releasing the UITableView in both of the ViewControllers.

@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];
}

推荐答案

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

First, do I read your code correctly, that your UITableView is not defined in the @interface? If that's so, you've defined myTable to be a global variable. That's not a good idea, though I'm surprised the linker didn't complain if you used the same global variable in two .m files (but it would certainly explain why using the same name caused problems). You really want your UITableView to be an instance variable. You could define the private instance variable at the top of your .m file as follows (put this before the @implementation):

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

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

If you do this, then it doesn't matter whether the name of your instance variable in one class happens to be the same as one in another class. The scope of an class instance variable is limited to that class. (By the way, as a matter of style, many people preface their class instance variables with underscores, generally to differentiate them from class properties and local variables.)

第二(与您的原始问题无关),我建议在 viewDidLoad 中发布,因此:

Second (and unrelated to your original question), I'd suggest releasing in viewDidLoad, thus:

- (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 语句.)

(And, obviously, remove the release statement from your dealloc.)

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

There's no reason to defer the release: When you alloc/init, it has a retain count of +1, when you addSubview it gets a retain count of +2, and when you release, you simply return the release count back to +1 (meaning that it won't be dealloced because self.view is retaining it but when the view eventually releases it, your tableview will be dealloced automatically for you). There are, though, good reasons to not defer it (your original code will leak if you got a didReceiveMemoryWarning after pushing to a new view controller).

如果您使用 ARC,这种愚蠢的内存管理问题通常会为您解决,但鉴于您没有使用 ARC,您可能需要调整发布位置.

If you use ARC, this sort of silly memory management issue is generally cleaned up for you, but given you're not using ARC, you might want to adjust where you release.

这篇关于释放/访问不同类中同名的不同对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆