- ベストアンサー
iPhoneアプリのプログラミングに関する質問です
- iPhoneアプリのプログラミングに関する質問です。アプリの開発経験がありますが、プログラムに関してはアマチュアです。
- 作成したアプリが一回目は正常に動作するが、シミュレーターの再起動後にフリーズや落ちる問題が発生しています。メモリの解放を試みましたが効果はありません。
- アップルのサンプルコードやチュートリアルを参考にしても問題を解決することができませんでした。質問者は問題の原因が分かっておらず、どのような方向で考えるべきか教えて欲しいとしています。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
-(void)viewDidLoad{ [super viewDidLoad]; hana0 = [UIImage imageNamed:@"hanamarunasi.png"]; hana1 = [UIImage imageNamed:@"akamarutoumei.png"]; } この箇所に問題があります。 iPhone SDK(iOS SDK)を勉強するのに、なんらかの書籍を参考になさっていると思いますが、上級者向けでなければ、どの書籍でもかならず、メモリ管理(オブジェクトの管理)に関して1章を割いているはずです。その章を熟読してください。 iPhone、iPod touch、iPadは、256MBないし512MBという、限られたメモリ容量でプログラムを動かしており、きちんとしたメモリ管理が要求されます。おなじObjective-C言語でプログラムを開発するMacintoshでは、GB単位のメモリ容量をいかして、プログラマがメモリ管理をせずにすむような手法(ガベージコレクションといいます)が可能ですが、iOSでは意図的にプログラマがメモリ管理をしなければならないようになっています。つねにオブジェクト(インスタンス)の生成から開放までの、ライフサイクル(オブジェクトの一生)を意識して、プログラムしなければいけません。オブジェクトが開放されたあとで、そのオブジェクトをほかのオブジェクトが参照しようとすると、エラーが発生します。 Objective-Cのすべてのクラスで、初期化メソッドを2種類用意しています。NSStringを例にとると…… [[NSString alloc] init]; [NSString string]; 前者の初期化メソッドでは、retainCount(NSObject Protocolのメソッド)が1になりますが、後者はそうならず、autoreleaseの状態になります。すなわち[NSString string]は、[[[NSString alloc] init] autorelease]とおなじになります。autoreleaseは、当面の役目が終わったら、いつ開放してもかまいませんよ、というメソッドです。 さて、UIImageのimageNamed:メソッドは、インスタンスをautorelease状態で生成します。UIImageインスタンスは、UIImageViewにすぐに取り込んでしまうか、UIViewのdrawRect:メソッドですぐに描画するのが、主な役目なので、さっさと開放したいインスタンスです。今回の場合は、もとインスタンスが存続している間、ずっと保持する必要があるので、ちゃんと保持する処理をしなければいけません。 hana0 = [[UIImage imageNamed:@"hanamarunasi.png"] retain]; このようにretainメソッドを使って、retainCountを1増やすことによって、保持します。
その他の回答 (1)
- harawo
- ベストアンサー率58% (3742/6450)
まず、ほかのインスタンスから「MondaiViewController」インスタンスの変数、hana0、hana1を参照することがなければ、このふたつをプロパティにする理由がありません。 引用したコードはすべてではありませんね?おそらく(推測ですが)省略して引用しなかった箇所に、「EXC_BAD_ACCESS」を引き起こす原因があるのではないかと考えられます。 よくある間違いが、インターフェイス部で宣言しただけで、生成していない、初期化していない、しているつもりだがそうなっていないということです。hana0、hana1を生成、初期化しているコードを含む箇所を引用してください。 ※本題以外で、気になった点: > シミュレーターの下にある□ボタンで終了させた後に、再度起動させて動かすと、UIImageを呼び出すところで、フリーズしたり落ちたりします。 ホームボタンを押しても、アプリは終了しません。サスペンド状態になっているだけ。なので、「UIImageを呼び出す」こともしていません。
補足
前回も助けていただいたharawoさん、ありがとうございます。書籍などのサンプルプログラムを参考にぎりぎりの知識で作成しているので、アドバイスの意味を完全に理解出来ている訳ではありませんが、ホームボタンでアプリが終了しているわけではないことは、分かりました。 普通にこのプログラムを動かしている限りにおいては、正常に動くのですが、なぜ、ホームボタンを押した後に再度動かすとアプリが落ちるのか、さらに不思議になりました。(一度落ちた後に、動かすと普通に動きます。) プログラムのどこがhana0,hana1を生成、初期化している部分か、はっきりと分かっているわけではありませんが、字数制限いっぱいまで重複する部分やコメントは削りながらコピーしました。 この程度の知識で、アプリをつくることが無謀なことかもしれませんが、何とか頑張りたいと思います。よろしくお願いします。 #import <UIKit/UIKit.h> @interface MondaiViewController : UIViewController { UIImage * hana0; UIImage * hana1; IBOutlet UITextField *mondai; IBOutlet UITextField *kaitou; IBOutlet id syoujyunkoujyunkubetu; IBOutlet id jidaikubetu; IBOutlet id taitoru; IBOutlet UIImageView *hana; } @property (nonatomic, retain) UIImage * hana0; @property (nonatomic, retain) UIImage * hana1; -(IBAction) seikaihyouji:(id)sender; -(IBAction) mondaisentaku:(id)sender; -(IBAction) kaisi:(id)sender; -(IBAction) marutuke:(id)sender; -(IBAction) syoujyunkoujyunsentaku:(id)sender; -(IBAction) jidaisentaku:(id)sender; @implementation MondaiViewController @synthesize hana0; @synthesize hana1; int jidai,syoukou,miss; char kuuhaku = ' '; int tugi; -(void)viewDidLoad{ [super viewDidLoad]; hana0 = [UIImage imageNamed:@"hanamarunasi.png"]; hana1 = [UIImage imageNamed:@"akamarutoumei.png"]; } -(IBAction) jidaisentaku:(id)sender{ switch ([jidaikubetu selectedSegmentIndex]) { case 0: jidai = 0; tugi = 0; break; case 1: jidai = 1; tugi = 0; break; case 2: jidai = 2; tugi = 0; break; default: break; } } -(IBAction) syoujyunkoujyunsentaku:(id)sender{ if (jidai == 0) { switch ([syoujyunkoujyunkubetu selectedSegmentIndex]) { case 0: syoukou = 0; tugi = 0; break; case 1: syoukou = 1; tugi = 0; break; case 2: syoukou = 2; tugi = 0; break; default: break; } } -(IBAction) kaisi:(id)sender{ [hana setImage:hana0]; [kaitou setText:[NSString stringWithFormat:@"%c",kuuhaku]]; [kaitou setTextColor:[UIColor blackColor]]; if (jidai == 0 && syoukou == 0 && tugi == 0) { [mondai setText:@"あああああ"]; } この後、同様な形が問題の数だけ続きます。 -(IBAction) marutuke:(id)sender{ if (jidai == 0 && syoukou == 0 && tugi == 0) { int miss = 0; int kai = [[kaitou text] intValue]; if (kai == 111) { [kaitou setTextColor:[UIColor blackColor]]; [hana setImage:hana1]; } else { [kaitou setTextColor:[UIColor redColor]]; [hana setImage:hana0]; tugi = tugi - 1; miss = 1; } } この後、同様に続きます。 -(IBAction) seikaihyouji:(id)sender{ if (jidai == 0 && syoukou == 0 && tugi == 0) { //正解を表示する [kaitou setText :@"111"]; } この後、同様に続きます。 -(IBAction) mondaisentaku:(id)sender{ [hana setImage:hana0]; [mondai setText:@" "]; [kaitou setText:[NSString stringWithFormat:@"%c",kuuhaku]]; [kaitou setTextColor:[UIColor blackColor]]; tugi = 0; [kaitou endEditing:YES]; } - (void)dealloc { [hana release]; [hana0 release]; [hana1 release]; [mondai release]; [kaitou release]; [syoujyunkoujyunkubetu release]; [jidaikubetu release]; [taitoru release]; [super dealloc]; }
お礼
harawo様 ありがとうございます。ご指摘の通り訂正すると、きちんと動作するようになりました。 このような場で、お名前も知らず、きちんとお礼出来ないのが心苦しい限りですが、重ねてお礼申し上げます。 ここまでアプリを作ってきて、地方在住で身近にXcodeを用いてプログラムをしている知り合いがいない環境で、独学での開発はだんだん無謀なことに思えてきていましたが、harawoさんのような親切な方のおかげで前へ進むことが出来ています。 私の作ったアプリが、どれだけ人の役に立つかは分かりませんが、この御親切に応えるためにも、少しでも誰かの役に立つアプリを作っていきたいと思います。 ありがとうございました。