Day: January 28, 2014

obj.C:徐々に進化、完璧に理解

疑問に思っていたことがだいぶわかってきました。

viva Cocoa Objective-C入門にしたがって学習しているのですが、基礎知識の欠如が進捗を妨害し、消化するのに時間がかかってしまいました。

やはり、参考にしたサンプルコードのmodel、control、stringといった変数やクラス名を別のユニークなものに変更することで、わからなかったこと、不思議に思っていたことについての理解が深まりました。多分、今のところは、それでいいと思われます。この先、どこかでその考えに習性が必要になったとしても、この地点までは明確に後戻りできるし、2つの考え方をすることでいずれにも行けるので問題はないと考えます。

メソッドのheader(.h)、implement(.m)とその呼び出し方

①MesaModelのheader(.h)
@interface MesaModel : NSObject
{NSString *MesaModelBuffer;} //buffer1
– (void)setString:(NSString *)aString;

②MesaModelのimplement(.m)
– (void)setString:(NSString *)aString

③メソッドの呼び出し方
例1 [textViewArea setString:@”Hello”]
※ headerには、次のように定義してあります。
@interface MesaCont : NSObject  <NSTextViewDelegate>
{
MesaModel *MesaModelBuffer;   //buffer2
IBOutlet NSTextView *textViewArea;
}

機能:例1では、メソッドsetStringにHelloを送り、textViewAreaに設定してもらっています。メソッドは【出力 メソッド名 入力】という形式になります。t最終的には、extViewAreaがUIと接続されたとき、UIに文字が表示されることになります。

例2 [MesaModelBuffer setString:[[textViewArea string] copy]] //buffer2
次の例2では、[[textViewArea string] copy]]をMesaModelBufferに設定してもらっています。

なお、このメソッドはクラスMesaModelにsetterとして記述されています。メソッドの呼び出しはクラスMesaContに記述されています。

<><><><><>

変数名を変更

ここからが問題で、setterメソッドsetStringの中でMesaModelBuffer = aString; というラインがあります。buffer1とbuffer2は同じ名前のMesaModelBufferなので最初は同じものと思っていたのですが、よくよく見て行くと別物のようなのです。

混乱がはじまったのはこのあたりからです。それで、MesaContのMesaModelBufferをMesaModelAddrと変更しました。MesaModelBufferAddr = [[MesaModel alloc] init]によりallocとinitでMesaModelを生成したときにクラスMesaModelのポインタが入っているからです。変更後は次のようになります。
.h
@interface MesaCont : NSObject  <NSTextViewDelegate>
{
MesaModel *MesaModelAddr;   //buffer2
IBOutlet NSTextView *textViewArea;
}
—–
.m
例2 [MesaModelAddr setString:[[textViewArea string] copy]] //buffer2

例2のMesaModelClassAddrはポインタなので、このメソッドの形式は【出力エリアのポインタ setString 文字列】ということになり、例1のtextViewAreaもポインタだったということになり、「HelloをtextViewAreaが示すバッファに 設定する」「[[textViewArea string] copy]]をMesaModelClassAddrが示すバッファに設定する」という意味になります。

だれも近場に先生がいませんので、とりあえず、そういうふうに理解しておくことにしました。

<><><><><>

グローバル変数で定義した場合

そうしたことを踏まえて、次の3つの変数をMesaContにグローバル変数を定義してエラーがでないかどうか、正しく動くかどうか確認することにしました。定義は@interfaceの直前にしました。この用法が適切かどうかは別問題で、確認したかったことはMesaContでのみ変数を定義したいという点でした。

  • MesaModel *MesaModelBufferAddr;  // alloc/initで得たMesaModelのポインタを格納
  • NSString *MesaModelBuffer;  // MesaModelでaStringを格納するバッファ
  • NSString *R15;  // MesaModelの(NSString *)string の返り値

ほかのクラスやメソッドのオブジェクトを違う箇所で触ると、サスペンドしたときに問題が出るということです。確保したメモリが自分の場所にないとき、グローバル変数で定義しても意味をなさないと思うのですが、現時点では自分で確保する方法までわかっていないのでこれで良しとします。

解明できていない点:
1. [[textViewArea string] copy]]のcopyが解明しきれていません。とりあえず、先送りです。
2. setStringでMesaModelBufferAddr以外を指定するケース。
Ans. これはあまり考えるまでのことはなく、id  workBufferAddr;を定義し、ここにMesaModelBufferAddrを代入して試して、同じ結果が得られればOKということになります。あとはバッファのアドレス(ポインタ)をそのid変数にどう設定するかの問題ですが、それは先送りとします。

MesaCont.h

スクリーンショット 2014-01-28 14.20.10

MesaCont.mスクリーンショット 2014-01-28 14.21.02

MesaModel.hスクリーンショット 2014-01-28 14.21.27

MesaModel.mスクリーンショット 2014-01-28 14.21.56