0

私は2つのプロパティを持つクラスを持っています:

@interface Contact : NSObject {
    NSString *lastname;
    NSString *lastNameUpper;
}

lastname をプロパティとして宣言しました (そして .m ファイルで合成します):

@property (nonatomic, retain) NSString *lastname;

ただし、lastNameUpper にアクセスする独自のメソッドを作成したいので、メソッドを宣言しました。

- (NSString *) lastNameUpper;

そしてそれを次のように実装しました:

- (NSString *) lastNameUpper {
    if (!lastNameUpper) {
        lastNameUpper = [lastname uppercaseString];
    }
    return lastNameUpper;
}

これは問題なく動作しますが、頻繁に呼び出されるため、多くの一時オブジェクトが呼び出されます。興味深いことに、Instruments には多くの「Malloc (4k)」が表示され、アクセスされるたびに数が増加しlastNameUpperます。また、メモリが に割り当てられていることもわかりますobjc_retailAutoreleaseReturnValue

プロジェクトを ARC に変換する前はこれで問題なく機能していたので、メソッド シグネチャに ARC 固有の追加をいくつか行う必要があると想定していますが、機能させることができないようです。

助言がありますか?

4

2 に答える 2

2

0: NSString プロパティをコピーする必要があります。

 @property (nonatomic, copy) NSString * lastname;

文字列を返すことは、コピーすることで実装されていると思います。

いいえ。不変文字列のコピーは保持操作です。これをプロファイラーで実行するだけで、時間とメモリにかかるコストを確認できます。また、この場合、暗黙のコピーはありません。

アップデート

これを Lion-64 でテストしました。変更可能な文字列uppercaseStringを返す場合があります。

安全のために、 : の結果のコピーを割り当てることを検討してuppercaseStringくださいlastNameUpper = [[lastname uppercaseString] copy];。実装で文字列をどのように使用したかによって、割り当てが増減する可能性があります。プロパティをコピーすると、割り当てるたびにコピーが作成されます。簡単な一般化はコピーを割り当てることであり、残りは通常それ自体で処理されます。

テストプログラム

// ARC enabled
#import <Foundation/Foundation.h>

@interface Contact : NSObject
{
    NSString * lastname;
    NSString * lastNameUpper;
}

@property (nonatomic, copy) NSString *lastname;

@end

@implementation Contact

@synthesize lastname;

- (NSString *) lastNameUpper {
    if (!lastNameUpper) {
        lastNameUpper = [lastname uppercaseString];
    }
    return lastNameUpper;
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int n = 0;
        while (n++ < 100000) {
            Contact * c = [Contact new];
            c.lastname = @"skjdhskjdhaksjhadi";
            NSString * lastNameUpper = c.lastNameUpper;
        }
    }

    return 0;
}
于 2012-04-20T16:14:54.140 に答える
1

メソッドをオーバーライドし- (void)setLastname:(NSString*)aLastname(によって自動的に作成さ@synthesize lastnameれ、既存のメソッドのように lastNameUpper を設定します。

次に、lastNameUpper プロパティを作成 (および合成) します。

@property (nonatomic, readonly) NSString *lastNameUpper;

これは lastNameUpper インスタンス変数のポインターを返すため、これにアクセスするたびにコピーを作成する必要はありません。

于 2012-04-20T16:13:54.777 に答える