2

私はobjective-c(そしてAppleのすべてのもの)の初心者です。

私は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、グローバル変数として定義されています。これは良い考えではありませんが、2 つの .m ファイルで同じグローバル変数を使用した場合にリンカが文句を言わなかったことに驚きました (ただし、同じ名前を使用すると問題が発生する理由は確かに説明されます)。あなたは本当にあなたUITableViewをインスタンス変数にしたいのです。次のように、.m ファイルの先頭にプライベート インスタンス変数を定義できます (これを の前に置きます@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.)

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

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

を延期する理由はありませreleaseん。割り当て/初期化すると、+1addSubviewの保持カウントがあり、+2 の保持カウントを取得すると、解放すると、単に解放カウントを +1 に戻します (つまり、は保持されているため割り当て解除されませんがself.view、ビューが最終的にそれを解放すると、テーブルビューは自動的に割り当て解除されます)。ただし、それを延期しない正当な理由があります (didReceiveMemoryWarning新しいビュー コントローラーにプッシュした後に元のコードがリークすると、元のコードがリークします)。

ARC を使用している場合、この種のばかげたメモリ管理の問題は通常はクリーンアップされますが、ARC を使用していない場合は、解放する場所を調整する必要がある場合があります。

于 2012-06-29T16:41:02.523 に答える