Objective-C - 読み取り専用プロパティはアンダースコア ivar で合成されませんか? 質問する

Objective-C - 読み取り専用プロパティはアンダースコア ivar で合成されませんか? 質問する

私の理解が正しければ、Objective-C では、プロパティはゲッターとセッターを使用して自動的に合成され、インスタンス変数はアンダースコア ( _ivar) が先頭に付いたプロパティ名として宣言されます。

つまり、このコード:

メイン.m

#import <Foundation/Foundation.h>
#import "hello.h"

int main(int argc, char *argv[])
{

    @autoreleasepool {

        Hello *hello = [[Hello alloc] init];
        NSLog(@"%@", hello.myString);

        return 0;

    }

}

こんにちは

#import <Foundation/Foundation.h>

@interface Hello : NSObject
@property (copy, nonatomic) NSString *myString;
@end

こんにちは。

#import "hello.h"

@implementation Hello

-(Hello *)init
{

    if (self = [super init]) {
        _myString = @"Hello";
    }

    return self;

}

-(NSString *)myString
{
    return [NSString stringWithFormat:@"%@ %@", _myString, @"World"];
}

@end

次のようにコンパイルして実行できます:

bash-3.2$ clang -framework Foundation main.m hello.m -o hello
bash-3.2$ ./hello
2013-05-27 13:20:39.738 hello[23320:707] Hello World

ここで、myString プロパティを次のように readonly に変更します。

@property (readonly, copy, nonatomic) NSString *myString;

その後、コンパイルしようとするとエラーが発生します:

hello.m:11:9: error: unknown type name '_myString'; did you mean 'NSString'?
        _myString = @"Hello";
        ^~~~~~~~~
        NSString

つまり、_myString定義されていません。コンパイラはインスタンス変数 _myString を使用してプロパティを合成しませんでしたか? 自分で合成したときに動作するかどうかを確認してみましょう。

hello.m の実装では:

@synthesize myString = _myString;

これで再び動作するようになりました:

bash-3.2$ clang -framework Foundation main.m hello.m -o hello
bash-3.2$ ./hello
2013-05-27 13:36:59.916 hello[24219:707] Hello World

そこで、私の質問は、プロパティで使用したときに、アンダースコア ivar で自動的に合成されないのはなぜかということですreadonly。それとも、Objective-C の仕組みの理解がまったく間違っているのでしょうか。

何が起こっているのか、そしてなぜ起こっているのかを本当に理解したいので、説明的な回答をいただければ幸いです。

よろしくお願いします。

ベストアンサー1

プロパティとは自動的に合成されない実装する場合必要なすべてのアクセサメソッド(読み取り専用プロパティの場合は getter、読み取り/書き込みプロパティの場合は getter + setter)。

読み取り専用プロパティのgetter メソッドを実装しているため-(NSString *)myString、自動合成されません。プロパティ値をバックアップするために getter にインスタンス変数が必要な場合は、合成ステートメント (実行したように) またはインスタンス変数を追加する必要があります。

おすすめ記事