0

以下の1行目と2行目の違いを知りたいだけです。

_subtitle = @"Test"; //Line 1
_subtitle = [NSString stringWithFormat: @"Test"]; //Line 2

私がその質問をした場合、それは MKAnnotation を使用して問題が発生したためです。次のメソッドでは、MKAnnotation の字幕デリゲート プロパティ (非アトミック、コピー、読み取り専用) を更新しようとしています。しかし、ライン2を使用するとゾンビが発生し、ライン1を使用するとゾンビが発生したように見えます.だから私の質問はなぜですか?

- (void) initCoordinateWithAddress:(NSString*)address;
{
self.address = address;

CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString: address completionHandler:^(NSArray *placemarks,NSError *error)
{
    CLPlacemark *place = [placemarks objectAtIndex:0];
    _coordinate = place.location.coordinate;
    _title = self.address;
    _subtitle = @"Test"; //Line 1: don't crash
     _subtitle = [NSString stringWithFormat: @"Test"]; //Line 2: crash
    //_subtitle = [[NSString stringWithFormat: @"[%.2f,%.2f]", self.coordinate.latitude, self.coordinate.longitude] copy];
    _isInit = YES;

    [self.customDelegate didCalculateCoordinate: place.location.coordinate forAnnotation: self];
}];

}

私は実際にcopyメソッドを使用して問題を解決しましたが、1行目と2行目の違いはまだわかりません。違いを理解するのを手伝ってくれる人がいれば、感謝します。

編集:

1- ARC を使用していない

2- _subtitle は @synthesize subtitle = _subtitle; から来ます。サブタイトルは MKAnnotation プロトコルの一部であり、nonatomic、readonly、copy のプロパティがあります。

よろしく、 シリル

4

5 に答える 5

2

ARC を使用していない場合、答えは簡単で、Anoop Vaida が書いたものです。ただし、もう少し説明が必要だと思います。

この行

_subtitle = @"Test";

文字列リテラルへの参照を作成します。ファウンデーションの現在の実装で保持カウントをピークにすると、それが非常に大きな数であることがわかります(NSIntegerMaxだと思います)。-releaseおよびのコード-retainが保持カウントのこの値に遭遇した場合、それらはそれを減少または増加しません。したがって、文字列リテラルには無限の寿命があります。

この行:

_subtitle = [NSString stringWithFormat: @"Test"];

あなたが所有していない文字列を作成します。所有権を主張するための措置を講じない限り、いつでも消える可能性があります。最も可能性が高いのは、自動解放プールが空になったときです。あなたのオプションは、あなたが所有する文字列を作成することです

_subtitle = [[NSString alloc] initWithFormat: @"Test"];

またはそれを保持します。

_subtitle = [NSString stringWithFormat: @"Test"];
[_subtitle retain]; // Can be combined with the previous line if you like.

またはそれをコピーする

_subtitle = [[NSString stringWithFormat: @"Test"] copy];

すべての場合において、上書きする前に _subtitle の以前の値を解放する必要があることに注意してください。そうしないと、たとえばリークが発生します。

[_subtitle release];
_subtitle = [[NSString alloc] initWithFormat: @"Test"];

これが、プロパティを持っている方が良い理由です。MKAnnotation の字幕プロパティが読み取り専用だからといって、独自の読み取り/書き込みプロパティで上書きできないわけではありません。例えば

@interface MyAnnotation : NSObject <MKAnnotation>

// other stuff

@property (readwrite, copy, nonatomic) NSString* subtitle; 

@end

それを合成すると、すべての正しいメモリ管理コードが得られ、次のことができます。

[self setSubtitle: [NSString stringWithFormat: @"test"]];

または、ドット表記を使用する必要がある場合

self.subtitle = [NSString stringWithFormat: @"test"];
于 2013-05-30T09:25:07.660 に答える
1

あなたの解決策は、文字列の初期化がどのように機能するかを理解することではないと思いますが、ブロックが変数を処理する方法について詳しく説明します。

私がそれについて考えるとき、ivar ではなくプロパティで access _subtitle を試してみたいと思うかもしれません。

self.subtitle

これにより、保持カウントが増加し、すべてが正常に機能し続けるはずです。

于 2013-05-29T14:37:51.583 に答える
1

以下の1行目と2行目の違いを知りたいだけです。

_subtitle = @"テスト"; //ライン1

_subtitle = [NSString stringWithFormat: @"Test"]; //2行目

上記だけを尋ねると、これらは両方とも同じです。

コードをチェックすると、違いがはっきりとわかります。

ブロックが終了すると解放される新しいautoreleasedを作成しています。subtitle

于 2013-05-29T14:06:05.890 に答える