前回の続きです
前回の実験コードで警告文が表示されていたため、その点について確認したいと思います。
"Writable atomic property 'name2' cannot pair a syncthesized getter with a user defined setter."
目的
初めてのプログラミング言語に苦戦されている方やこれから開発を行おうとしている方は、問題の解決方法を身につける必要があります。
インターネットで、その解決手段の説明ではなく答えが先に見つかることが多いので便利になりました。
しかし、必ずしも答えが用意されている訳ではないため、以下のような解決までのプロセスも含めて書いてみました。
いつものことではありますが、十分に推敲して書いている訳ではないため内容の信憑性などは他の記事よりは低めと思って頂ければと思います。
それでも宜しければ、以下の内容をどうぞ。
エラー内容を読み取る
この世界のエラーメッセージは多くの場合は英語で表示されます。
そのため、英語を理解することでスムーズにエラーの内容を把握して正しく修正することが可能だと思います。
私の場合は英語の勉強を疎かにしてしまったため、このままでは単語しか分かりません。
しかし今までの経験からするとエラーメッセージレベルであれば、Google翻訳レベルの翻訳で伝えたいことを大まかに知ることが出来るので
かんたんな開発を行うのには問題ありません。
翻訳してみた
Google翻訳結果:
書き込み可能アトミックプロパティ 'NAME2」は、ユーザ定義のセッターでsyncthesizedゲッターをペアにすることはできません。
単語を拾ってみました
・書き込み可能なアトミックプロパティ
・ユーザ定義のセッター
・syncthesizedゲッター
書き込み可能なアトミックプロパティについて
「書き込み可能な」については、アクセス制御オプションのことを指していると予測。
アクセス制御は以下の2つある。
・readonly
・readwrite
今回は指定していないため、デフォルトはreadwriteとなることから今のところは状況にマッチしています。
「アトミックプロパティ」については、スレッドセーフの保証可否オプションのことを指していると予測。
アトミックの指定は以下の2つある。
・nonatomic
・atomic
今回は指定していないため、デフォルトはatomicとなることから今のところは状況にマッチしています。
ユーザ定義のセッターについて
前回の確認でセッターを自分で定義していることを指していると思います。
@property (setter=fullName:) NSString *name2;
syncthesizedゲッターについて
プロパティ宣言したコードをビルドすると自動的にgetter/setterが生成されていて、今回の場合はsetterのみユーザ定義したので自動生成されたgetterとはペアにできませんよ のようなことを言っていると感じ取りました。
ここまでの情報で少し考えてみます
まず問題なのは、ユーザ定義のセッターと自動生成されるゲッターをペアに出来ない点ということがわかりました。
解決方法の仮説を以下のような考えました。
・書き込み可能なアトミックプロパティ以外なら可能かもしれない
・ユーザ定義のセッターを用意した場合は、ゲッターをユーザ定義してやる必要があるかもしれない
検証開始
・書き込み可能なアトミックプロパティ以外なら可能かもしれない
まずは書き込み可能ではないパターンを考えてみました。
もちろん考えなくても直感的に気づいてはいるのですがsetterを明示的に指定しておきながら、readonlyオプションを指定することが出来ないのでこのパターンは成立しません。
次にアトミックプロパティではないパターンを考えてみました。
結果的にこのパターンは警告は表示されなくなりました。
@property (nonatomic, setter=fullName:) NSString *name2;
・ユーザ定義のセッターを用意した場合は、ゲッターをユーザ定義してやる必要があるかもしれない
試しにgetterをユーザ定義して追加しました。
結果を先に書いておきますが、以下のコードだとコンパイルエラーとなります。
@property (getter=name, setter=fullName:) NSString *name2;
-(void)fullName:(NSString*)value {
//self.name2 = value; : NG 無限ループします
_name2 = value;
}
-(NSString*)name {
return _name2;
}
エラーメッセージ : "Use of undeclared identifier '_name2'"
エラー内容としては、_name2は宣言されていませんという内容です。
getter、setterの両方をユーザ定義するとどうやらビルド時に自動生成されていた_name2メンバー変数が作成されないようです。
自動生成されないのであれば、自分でコーディングしてやれば問題ないのでは? と考えてみたのでまずはコーディングしてみました。
// Person.h
@interface Person : NSObject
{
NSString *_name2;
}
結果は、コンパイルエラー、警告の両方が表示されなくなりました。
まとめ
解決まではあえて記載していません。(途中で時間がなくなっただけですが・・・)
流れとしてはこのように推測して試すという方法を書いてみましたが、情報が見つからない場合はという前提条件があります。
まずはリファレンスなどを確認するのが、無難な方法だと思います。
今回は以上です。