0

私はこのコードを読んでいましたが、リリースsetRegions後に呼び出されRootViewControllerます:少し奇妙だと思います:リリースされて「所有」していRootViewControllerても、まだアクセス可能であることを意味しますか?self.navigationController

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    // Create the navigation and view controllers
    RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
    UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
    self.navigationController = aNavigationController;
    [aNavigationController release];
    [rootViewController release];

    [rootViewController setRegions:[Region knownRegions]];

    // Configure and display the window
    [window addSubview:[navigationController view]];
    [window makeKeyAndVisible];
}

ありがとう

4

3 に答える 3

4

これは悪いコードです。

オブジェクトは、それを気にする限り、別のオブジェクトを保持する必要があります。そしてこの場合、そのルールは破られています。rootViewControllerがリリースされ、ご存知のように、メソッドが呼び出されます。これは危険な場合があります。

この場合、それは機能します。これはrootViewController、それを保持する別のオブジェクトに渡されるためです。したがって、リリースしても、保持カウントは正であり、割り当てが解除されません。したがって、それへの参照は引き続き機能し、それに対して呼び出されるメソッドは正常に機能します。

しかし、いくつかの実装が変更され、initWithRootViewController:何らかの理由でその引数を保持しなくなったとしましょう(常に実際に行うことはできないという仮定)。割り当てが解除されるため、突然これがすべてクラッシュしrootViewControllerます。

このファンクを修正するに[rootViewController release];は、この関数でそのオブジェクトの最後の有用な参照の後に移動する必要があります。そうすれば、コードはより堅牢でより正確になります。

- (void)applicationDidFinishLaunching:(UIApplication *)application {

    // Create the navigation and view controllers
    RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];
    [rootViewController setRegions:[Region knownRegions]];
    UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
    self.navigationController = aNavigationController;

    // Release temporary objects since we've now sent them to other other objects
    // which may or may not retain them (we don't really care which here)
    [aNavigationController release];
    [rootViewController release];

    // Configure and display the window
    [window addSubview:[navigationController view]];
    [window makeKeyAndVisible];
}

最後に注意すること:releaseそしてそれdeallocは非常に異なるものです。 release必ずしもオブジェクトを破壊するわけではありません。retainカウントを1つ減らすだけです。そして、そのretainカウントがゼロになった場合にのみ、オブジェクトの割り当てが解除されます。したがって、このコードは、releaseが発生するが、をトリガーしないために機能しdeallocます。

于 2012-04-04T01:33:13.023 に答える
1

上記は非常に危険なコードです。たまたまうまくいくかもしれませんが、運が良かっただけです。変数を解放した後は、変数にアクセスしないでください。実際、変数がnilすぐにスコープから外れない場合は、変数を解放した後すぐにに設定することをお勧めします。リリースモードでのみこれを行う人もいるため、次のようなマクロを作成します。

#ifdef DEBUG
#define RELEASE(x) [x release];
#else
#define RELEASE(x) [x release]; x = nil;
#endif

nilこの理由は、リリースモードでは少し安全でありながら、デバッグモードでバグをキャッチするのに役立つためです(サイレントポインタだけでなくクラッシュすることによって)。

ただし、いずれの場合も、変数を解放した後は、変数にアクセスしないでください。

于 2012-04-04T01:31:21.917 に答える
1
RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain];

(objectA が作成され、保持カウントが 1 であり、rootViewController がそれを指している)

UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];

(objectB が作成され、保持カウントは 1、aNavigationController はそれを指している) (objectA 保持カウントは現在 2 であり、rootViewController と self.aNavigationController のいくつかのプロパティの両方がそれを指している)

self.navigationController = aNavigationController;

(現在、objectB の保持カウントは 2 です。aNavigationController と self.navigationController の両方がそれを指しています。self.navigationController が保持プロパティであると仮定します)

[aNavigationController release];

(現在、objectB 保持カウントは 1 ですが、aNavigationController と self.navigationController の両方がそれを指しています)

[rootViewController release];

(現在、objectA 保持カウントは 1 ですが、rootViewController と self.aNavigationController の一部のプロパティの両方がそれを指しています)

[rootViewController setRegions:[Region knownRegions]];

(rootViewController を使用して objectA にアクセス) (これは良くありません)

以下は私の推奨される方法です:

RootViewController *rootViewController = [[[RootViewController alloc] initWithStyle:UITableViewStylePlain] autorelease];
[rootViewController setRegions:[Region knownRegions]];

UINavigationController *aNavigationController = [[[UINavigationController alloc] initWithRootViewController:rootViewController] autorelease];
self.navigationController = aNavigationController;
于 2012-04-04T01:41:09.447 に答える