Obj.C

obj.C:stringがダブルで混乱

setter / getterのgetterが呼び出されない原因を調べていたら、サンプルコードのstringが2種類ありそうなことを発見して行き詰まりました。

【結論】

  • メソッドのオーバーライドは、「スーパークラスのメソッドと同じ名前、同じ戻り値型、同じ引数のメソッドをサブクラスで定義することで実現」するという原則にもう一度戻り、上記の検証をやり直す必要がありますね。
    ➡その条件に合うようにしてやり直したのですが、結果は同じです。逆に、新たに[textViewAddr setString:@”Mesa”]; もオーバライドしているはずのメソッドに来ていませんでした。
    やれやれ。
    プロジェクトを作り直して最初から忠実にやっても同じような現象が出ているようなので、同じかどうか、いまからチェックします。
    ➡下記のOKと考えていたものはNGで、NGもNGと判明しました。新規プロジェクトで起こしたものは、OKとNGに分かれており、今、NGの解明をしています。
    問題の原因がわかりました。
    ①setter/getterメソッドMesaModel側で指定された変数を認識できていなかったことが原因で、MesaModel *変数名Addrという形式で必要なものを追加したらOKになりました。
    ②mcWorkBuffer2 = [textViewAddr string];の場合、textViewAddrはIBOutletのText Viewのポインタであり、[mmBuffer1Addr setString:[textViewAddr string]];のようにするべき。
    ※このあと、setter/getterメソッドの変数名をユニークなものに変えたときどうなるか、確認することにします。たとえば、stringをstringB等。

<><><><><>

getterの戻り値の変数名が違っていたとしても今のところチェックしていないのでロジック上の問題はないはずですが、viva Cocoa Objective-C入門のサンプルコードのstringは、もしかすると2つの違うことをさして利用されているのではないかという疑いが出て来ました。

MesaModel.m
– (NSString *)string   // getter
{
NSLog(@”NSS+++++++”);
return MesaModelBuffer;
}

viva Cocoa Objective-C入門の次のページに進んでサンプルコードを実装したら、- (NSString *)stringが呼び出されるケースが出て来ました。念のために変数は、次のように定義しています。

  • IBOutlet NSTextView *textViewArea;
  • MesaModel *MesaModelBufferAddr;

問題となっている現象:

  • [MesaModelBufferAddr setString:[[textViewArea string] copy]];の[textViewArea string]は呼び出されません。
  • NSLog(@” NO%@”, [MesaModelBufferAddr string]);は呼び出されます。

そこで、

  • – (NSString *)stringを- (NSString *)stringBに変更。
  • [MesaModelBufferAddr stringB]に変更。これはOK。
  • しかし、[textViewArea stringB]ではbuild error発生。それで[textViewArea string]のままbuild。

【調査】

入れ子だとわかりにくいので、MesaModelBuffer2 = [textViewArea string];という単純化したコードで調べることにしました。stringBに変えると、No visible @interface for NSTextView declares the selector stringBというエラーになりますので、このstringは別もののようです。

  • stringメソッドはText Viewから(正確にはNSTextから)そこに書かれているプレーンな(属性のない)文字列を取得するメソッド(viva Cocoa Objective-C入門の説明)

Xcode helpで調べると、stringはNSText Class ReferenceのメソッドでReturns the receiver’s text without attributes。文字列だけを取り出すメソッド。

  • [textViewArea string]は、textViewAreaの中身(atributeを除く文字列だけ)を意味する。厳密に言えば、「textViewAreaの中のポインタが指し示すメモリにあるatributeを除く文字列」ということになります。
  • すなわち、MesaModelBuffer2 = [textViewArea string];は、平たく言えば、「textViewAreaの文字列をMesaModelBuffer2に入れる」。厳密には、「textViewAreaの中のポインタが指し示すメモリにあるatributeを除く文字列」を「MesaModelBuffer2の中のポインタが指し示すメモリ」に入れる。

【考察】

  • 単純に考えると、「IBOutletで定義した変数を使った場合、getterメソッドを呼び出すことができない」となります。ポインタを別の変数に代入してもbuild errorになりますから、変数名というよりか、IBOutlet(or NSText)に関連しているのでしょうか。
  • 他方、getterメソッドstrngBは機能しているようですから、これこのままで良さそうです。
  • 最終的に、stringBをstringにしなければならないかどうか?同じにしないといけないのか、あるいは同じ方がいいのか?
    仮免許も取っていない初心者には、変数名やメソッド名が同じだと大混乱です。うだつは上がりませんが、調べることで勉強にはなります。時間のかけ過ぎです。

Categories: Obj.C, 技術

Tagged as: ,