プロが教えるわが家の防犯対策術!

Xcodeでiphoneアプリ勉強中の初心者です。

変数の値をオブジェクトの名前として利用する事は可能でしょうか?

(過去の質問履歴を探しましたが、他の言語については掲載されていましたが、xcodeやobject-cに関しては類似する質問を見つける事が出来ませんでした。)


例えば、3つのラベルが配置されていて、ソース中(.mファイル)に以下の記述があったとします。

labeldayo1.text= @"1";
labeldayo2.text= @"2";
labeldayo3.text= @"3";

こののラベル部分を

for (loop=1;loop<=3;loop=loop+1)
{
labeldayo(loop).text= [NSString stringWithFormat:@"%d",loop];
}

みたいな感じで、変数の値をオブジェクトの名前として利用する事は可能でしょうか??
もし可能な場合、どのような記述方法があるのか、ご教授いただけたら幸いです。

A 回答 (2件)

- (IBAction)labelhenkou


{
NSArray *objArray = [NSArray arrayWithObjects:@"labeldayo1",@"labeldayo2",@"labeldayo3",nil];
id obj;
for (obj in objArray)
{
loop = loop + 1;
tmpvalue = [NSString stringWithFormat:@"%d",loop];
[obj setText:tmpvalue];
}
}

ふたつのまちがいがあります。

(1) objArrayに、あなたはなにを登録していますか?「@"labeldayo1"」、「@"labeldayo2"」、「@"labeldayo3"」は、NSStringのオブジェクトです。UILabelのオブジェクトではありません。NSStringには、「setText:」というメソッドはありませんから、エラーが起きます。

(2) NSArray *objArray = [NSArray arrayWithObjects:@"labeldayo1",@"labeldayo2",@"labeldayo3",nil];
これは……
NSArray *objArray = [[NSArray alloc] initWithObjects:@"labeldayo1",@"labeldayo2",@"labeldayo3",nil];
と書き直しましょう。
あなたはなにかしらのObjective-CないしiOS SDK(iPhone SDK)の入門書で勉強なさっていますね?どの入門書でも、かならずといっていいほどメモリ管理に関して、1章を割いて解説しています。その章をていねいに、端から端まで熟読してください。
Objective-Cは、JAVAなどで装備されているガベージコレクション(Gabage Collection)がオプション扱いとなっており、iOSにおいては、オフになっています。メモリの管理、オブジェクトの生成と、保持(バッファリング)、そして開放を、プログラマが責任を持って処理しなければいけません。これは、256MB、512MBという限られたメモリ量で、最大の能力を発揮しようとすると、ガベージコレクションのために処理能力を割り当てる余裕がないためです。
「arrayWith~」メソッドのほうは、暗黙的にautoreleaseがセットされ、いつオブジェクトが開放されるか、だれにもわかりません。(たぶんだいじょうぶだけど)
「initWith~」メソッドのほうは、暗黙的にretainがセットされ、Retain Countを1プラスするので、releaseメソッドを送るまで、かならずそのオブジェクトの保持が約束されます。
プロジェクトのビルド時にエラーが出ず、アプリを実行している間に、アプリが落ちてしまうのは、だいたいオブジェクトが開放されたあとに、そのオブジェクトを参照しようとすることが原因です。(もちろんほかの原因もたくさんあります)

ということで、ひとつの考え方として、次のようにコードを書き換えると、問題を解消できます。ほかの書き方もあるでしょう。それは、あなたのアイデアしだいで、お好みの方法を選択してください。

- (IBAction)labelhenkou
{
NSArray *objArray = [[NSArray alloc] initWithObjects: labeldayo1, labeldayo2, labeldayo3, nil];
id obj;
int i = 1;
for (obj in objArray)
{
obj.text = [NSString stringWithFormat: @"%d", i];
i++;
}
[objArray release];
}
    • good
    • 0
この回答へのお礼

ありがとうございました!

> (1) objArrayに、あなたはなにを登録していますか?

ご指摘の通りです。
なるほど、、、納得です。
本当にありがとうございました。

お礼日時:2011/06/23 13:56

「object-c」ではなく、「Objective-C」です。

インターネット上の情報検索するときに、正式な名称をキーワードにするかしないかで、ヒットする確率が変わってくるでしょう。あなた自身にとって有利なのですから、ちゃんと正式な名称を覚えておきましょう。

Objective-Cは、Javascriptのようなインタプリタではなく、コンパイルして動くプログラムです。コンパイルした瞬間に、オブジェクト名というテキスト属性は消えてなくなってしまうので、おっしゃるようなことは期待できません。ちなみに、Objective-Cでは、「UILabel *label」とオブジェクトを宣言することからわかるように、オブジェクトをポインタとして取り扱います。ポインタですから、整数値によって、オブジェクトを識別することになります。

大量のオブジェクトを、列挙子(forやwhile)で処理するには、オブジェクトをコレクションクラス(NSArray、NSDictionaryなど)に格納しておくといいでしょう。

int i;
for (i = 0; i < [objArray count]; i++) {
[[objArray objectAtIndex: i] ~]; // オブジェクトの処理
}

こんな使い方です。

なお、Objective-C 2.0より、高速列挙子が採用され、ループ処理が高速になりました。上のサンプルを、高速列挙子を使って書き換えると、

id obj;
for (obj in objArray) {
[obj ~]; // オブジェクトの処理
}

こうなります。
    • good
    • 0
この回答へのお礼

ご教授ありがとうございます。
心から感謝いたします。

さて、教えて頂いた方法(「ループ処理をしてみた場合のTESTViewController.m」)を試してみましたところ、おかげさまでエラーは出ませんでした。
しかしながら、起動後にボタンを押した瞬間に落ちてしまいます。


======================================================
以下は TESTViewController.h
======================================================
#import <UIKit/UIKit.h>
@interface TESTViewController : UIViewController {
IBOutlet UILabel *labeldayo1;
IBOutlet UILabel *labeldayo2;
IBOutlet UILabel *labeldayo3;
}
- (IBAction) labelhenkou;
@end



======================================================
以下は、ループ処理をしない場合のTESTViewController.m
(正常に動きました)
※やり方は変えていますが、ボタンを押すとそれぞれ「1」「2」「3」と表示されます。
======================================================
#import "TESTViewController.h"
@implementation TESTViewController

- (IBAction)labelhenkou
{
[labeldayo1 setText:tmpvalue];
labeldayo2.text = [NSString stringWithFormat:@"%d",2];
labeldayo3.text = @"3";
}



======================================================
以下は、ループ処理をしてみた場合のTESTViewController.m
(エラー無し。立ち上がるが、ボタンを押した瞬間に落ちます)
======================================================
#import "TESTViewController.h"
@implementation TESTViewController

int loop = 0;
NSString *tmpvalue;

- (IBAction)labelhenkou
{
NSArray *objArray = [NSArray arrayWithObjects:@"labeldayo1",@"labeldayo2",@"labeldayo3",nil];
id obj;
for (obj in objArray)
{
loop = loop + 1;
tmpvalue = [NSString stringWithFormat:@"%d",loop];
[obj setText:tmpvalue];
}
}





自分なりにいろいろ考えて調べてみましたところ、ヘッダファイル中の
IBOutlet UILabel *labeldayo1;
IBOutlet UILabel *labeldayo2;
IBOutlet UILabel *labeldayo3;



IBOutlet UILabel *labeldayo[3];
みたいな感じで生成して、結びつけが出来れば可能なのかな?とも思いましたが、やはり上手くいきません。(そもそもインタフェースビルダーで結びつけが出来ませんです。。。)

お礼日時:2011/06/23 12:43

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!