iPhone開発についての質問

このQ&Aのポイント
  • iPhone開発についての質問です。AVAudioPlayerを利用したボタンタップで音が鳴り、再びタップで音を止める動作を実装したいのですが、止める処理が思い通りに動きません。
  • 質問内容は、xCode4でxibを利用している変数hogeFlgとAVAudioPlayerを使い、ボタンタップで音を再生、再びタップで音を止めるという動作を実装したいが、止める処理がうまく動かないというものです。
  • また、xibを利用しているために起動時にviewDidloadを読み込むかどうかもわからず、解決策がわからない状況です。
回答を見る
  • ベストアンサー

iPhone開発について

初歩的な質問ですが、お願い致します。 ボタンをタップで音が鳴り、再びタップで音を止めるという動きを AVAudioPlayerを利用し実装したいと考えておりますがストップが思い通りに動きません。 プレイは正常に動作しております。 xCode4 で xib を利用しております。 該当部分だけコードを以下に抜粋させていただきます。 hogeController.m - (IBAction)btn{ NSString *path = [[NSBundle mainBundle] pathForResource:@"hoge" ofType:@"mp3"]; NSURL *url = [NSURL fileURLWithPath:path]; AVAudioPlayer *oto = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; if (hogeFlg == NO){ hogeFlg = YES; [oto play]; }else{ hogeFlg = NO; [oto stop]; } } デバッグでは、2回目のタップで、[oto stop];は通過しております。 基本的なところが理解できていないためということはわかっているのですが、解決策がわかりません。 また、xib を利用しておりますので、起動時に、- (void)viewDidload を読み込むのかな? と思い、入れてみたのですが通っておりません。 本当は、ここでセットして、ボタンタップじでは、再生と停止の処理だけを入れたいのですが、そういうことは可能なのでしょうか。 どうぞ、よろしくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.1

> また、xib を利用しておりますので、起動時に、- (void)viewDidload を読み込むのかな? > と思い、入れてみたのですが通っておりません。 なにを「入れてみた」のですか?指示しているものがないので、意味が通じません。 それを置いておいても、ひじょうにあぶないコードであることは、まちがいありません。 Objective-Cでは、インスタンス(オブジェクト)を代入する変数がポインタであることはおわかりですね? ボタンを押すたびに「AVAudioPlayer *oto = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];」とインスタンスを新規生成していると、現在再生中のインスタンスを指し示すポインタが、「oto」でなくなってしまうため、メソッドによる制御が不能になってしまいます。まあ、停止できなくなって、とうぜんといえばとうぜんです。おなじサウンドリソースから生成したインスタンスだから、おなじインスタンスと考えるのは、間違いだということはわかりますね? Objective-Cで、C言語におけるグローバル変数と同等のものを使いたければ、インスタンス変数として、ヘッダファイル(@interface)に記述します。 AVAudioPlayerのインスタンスは、ファイルから読み込んで、再生可能な状態にするまで時間がかかるので、再生する前に前もって生成しておき、「prepareToPlay」メソッドで準備させておくことが肝心です。ここらへんの過程は、View Controllerクラスの「viewDidLoad:」メソッド内で処理しておくといいでしょう。 AVAudioPlayerクラスに限らず、生成したインスタンスは、使い終わったあとかならずバッファ開放することを心がけてください。これはオブジェクトのライフサイクルといって、Objective-Cだけでなく、オブジェクト指向言語すべてにあてはまることです。いつインスタンスを開放したらいいのかはっきりしないときのために、Objective-Cでは「dealloc」というメソッドが用意されており、このメソッド内でいつ開放したらいいのかはっきりしないインスタンスを開放するコードを書くようになっています。

RYO-88
質問者

お礼

ありがとうございました。 >なにを「入れてみた」のですか?指示しているものがないので、意味が通じません。 失礼致しました。メソッド自体です。 ご回答頂いた内容を調べながら修正して行きます。 ありがとうございました。

その他の回答 (1)

  • harawo
  • ベストアンサー率58% (3742/6450)
回答No.2

> 失礼致しました。メソッド自体です。 メソッドとは、なにをするメソッドですか?指示しているものが書いていないという意味では、私の質問に対する回答になっておりません。

RYO-88
質問者

お礼

-(void)viewDidLoad でも確認した所、動きました。 ちょこちょこ触っていたので、結局なぜ最初動かなかったのかが分からず気持ちが悪いですが、とりあえず解決できました。 本当に助かりました。ありがとうございます。

RYO-88
質問者

補足

はじめは、-(void)viewDidLoad に以下を入れておりました。 NSString *path = [[NSBundle mainBundle] pathForResource:@"hoge" ofType:@"mp3"]; NSURL *url = [NSURL fileURLWithPath:path]; AVAudioPlayer *oto = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; -(void)viewDidAppear:(BOOL)animated に入れましたら、思い通り動くようになりました。 -(void)viewDidLoad は、初回ロードされた時のみ -(void)viewDidAppear:(BOOL)animated は、画面が表示された後 に呼び出されていると思っていたのですが、2つは何か動きが違うのでしょうか。

関連するQ&A

  • xcodeの音を鳴らすのを遅らせる方法

    xcodeで音を鳴らしたいんですけど、 ボタンを押して数秒したら音が鳴るようにしたいんですけどどうしたらいいでしょうか? ループさせるので音源の最初を空白にするわけにはいきません。 あとAVAudioPlayerを使ったやり方だと助かります。 NSString *bgmPath = [[NSBundle mainBundle] pathForResource:@"music"ofType:@"mp3"]; NSURL *bgmUrl = [NSURL fileURLWithPath:bgmPath]; sound = [[AVAudioPlayer alloc] initWithContentsOfURL:bgmUrl error:nil]; [sound setNumberOfLoops:0]; //ここに指定した時間遅らせるというのを入れたい// [sound play]; どうかよろしくお願いします。

  • iphoneアプリの開発

    電卓アプリを作っています。 今困っているのは 1.割り算で小数点以下の計算ができない。 2.3つ以上の計算が(2×3×4のような)足し算しかできない。 3.間違えて数値を入力した場合に使うバックスペース的なボタンの作り方。 です。 どれか一つでもいいのでアドバイスいただけたらありがたいです。 #import "myViewController.h" @implementation myViewController // The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad. /* - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization. } return self; } */ // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. - (void)viewDidLoad { [super viewDidLoad]; startInput = YES; currentValue = 0; } -(IBAction)numberButtonPressed:(id)sender { UIButton *b = (UIButton *)sender; if( startInput ){ // 最初の1桁目が0なら表示しない if( b.tag == 0 ) return; // 新しく表示する文字列を作成 label.text = [NSString stringWithFormat:@"%d", b.tag]; startInput = NO; } else { // すでに表示されている文字列に連結 label.text = [NSString stringWithFormat:@"%@%d", label.text, b.tag]; } NSString *path = [[NSBundle mainBundle] pathForResource:@"button5" ofType:@"wav"]; NSURL *url = [NSURL fileURLWithPath:path]; AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; [audio play]; } -(IBAction)equalButtonPressed:(id)sender { currentValue = sum; sum = sum-sum; // 直前に押された演算子で場合分け if( operation == 0 ){ currentValue += [label.text intValue]; } else if( operation == 1 ){ currentValue -= [label.text intValue]; } else if( operation ==2){ currentValue *= [label.text intValue]; } else if (operation ==3){ currentValue /= [label.text intValue]; } // 表示の更新 label.text = [NSString stringWithFormat:@"%d", currentValue]; startInput = YES; label2.text =@"="; NSString *path = [[NSBundle mainBundle] pathForResource:@"button5" ofType:@"wav"]; NSURL *url = [NSURL fileURLWithPath:path]; AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; [audio play]; } -(IBAction)opButtonPressed:(id)sender { UIButton *b = (UIButton *)sender; // 現在値の保存 if( operation == 0 ){ currentValue= [label.text intValue]; sum +=currentValue; label.text =[NSString stringWithFormat:@"%d", sum]; } // 演算の保存 operation = b.tag; startInput = YES; if( operation == 0 ){ label2.text =@"+"; } if( operation == 1 ){ label2.text =@"-"; } if( operation == 2 ){ label2.text =@"×"; } if( operation == 3 ){ label2.text =@"÷"; } NSString *path = [[NSBundle mainBundle] pathForResource:@"button5" ofType:@"wav"]; NSURL *url = [NSURL fileURLWithPath:path]; AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; [audio play]; } -(IBAction)clearButtonPressed:(id)sender { label.text = @"0"; startInput = YES; label2.text =@""; NSString *path = [[NSBundle mainBundle] pathForResource:@"button5" ofType:@"wav"]; NSURL *url = [NSURL fileURLWithPath:path]; AVAudioPlayer *audio = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil]; [audio play]; } /* // Override to allow orientations other than the default portrait orientation. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations. return (interfaceOrientation == UIInterfaceOrientationPortrait); } */ - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc. that aren't in use. } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (void)dealloc { [super dealloc]; } @end

  • AVAudioPlayer インスタン

    iPhone の自作アプリで音声に関する場所を作成しているのですが AVAudioPlayerのインスタン作成場所について知りたいことがあります touchesMoved内 もしくは別クラスで音声を再生させる際 [ABC play];の上にコードを書き込み NSString *_ABC = [[NSBundle mainBundle] pathForResource:@"ABC" ofType:@"caf"]; ABC = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:_ABC] error:NULL]; [ABC play]; このようなコードになりました ここで思ったのですが 処理を実行する際、playだけを行ってくれればいいのに 上記コードだと2回目3回目の処理で毎回cafファイルを読み込みインスタンを生成する といった処理内容になってしまうのでしょうか? ツールを使用しメモリ使用率を確認したところAVAudioPlayerで メモリリークしているみたいです ログにはerror = 24 (Too many open files)と表示されます releaseもしていないのでそれも原因と考えられますが複数の音声を同時 もしくはバラバラ、もしくは同じ音声を連続で再生することもあるので releaseをどこに入れたらうまくいくのか理解できていません コードを書き込む位置も含めて簡潔でいいのでアドバイスをいただけるとありがたいです

  • NSTimerカウントダウンで音楽を停止するには?

    Xcodeで iPhoneアプリ作りに奮闘している初心者です。 NSTimerでカウントダウンタイマーを設定しましたが、タイマー終了とともに BGM音楽を停止したいのですが、.p ファイルに #import <AVFoundation/AVFoundation.h> と追加して、.m ファイルに タイマー終了時にイベントとして、 if (RestTime == 0) { timeflag = false; NSString *bgmPath = [[NSBundle mainBundle] pathForResource:@"xxxx"ofType:@"mp3" ]; NSURL *bgmUrl = [NSURL fileURLWithPath:bgmPath]; sound = [[AVAudioPlayer alloc] initWithContentsOfURL:bgmUrl error:nil]; [sound setNumberOfLoops:-1]; [sound stop]; とコードをいれてみましたが、タイマーは終了しても音楽は止まらず鳴りっぱなしです。 NSTimer周辺に詳しい方で、カウントダウンタイマー終了と同時に他の作動をとめる設定(プログラムコード)をお知りのかたお助けねがいます。 また、すでに鳴っている(他のページ又は同じページ,controller内の)音楽をタイマーに合わせて止めることが不可能なら、タイマースタートボタンを押すと同時に音楽をスタートし、タイマー終了とともに音楽を停止するプログラムコードを教えていただけたら助かります。 よろしくお願いします。

  • objective-Cについてご相談があります。

    現在objective-cを勉強中なのですが、 jsonについて教えて頂きたい事があります。 jsonのファイル・データ・オブジェクトそれぞれを 取得する必要があると習ったのですが、それらの違いが 今ひとつ分かりません。 下記のような記述なのですが、それぞれの違いをどなたか ご教示頂けないでしょうか。 // 対象Jsonファイル取得 NSBundle *bnd = [NSBundle mainBundle]; NSString *ptn = [bnd pathForResource:@"Test01" ofType:@"json"]; NSURL *url = [NSURL fileURLWithPath:ptn]; // Jsonオブジェクトの取得 NSURLRequest *req =[NSURLRequest requestWithURL:url]; NSData *dat = [NSURLConnection sendSynchronousRequest:req returningResponse:nil error:nil]; // Jsonデータの取得 NSDictionary *dick01 = (NSDictionary *) [NSJSONSerialization JSONObjectWithData:dat options:NSJSONReadingMutableContainers error:nil]; 以上、何卒宜しくお願い致します。

  • Objective-C

    NSString *path = [[NSBundle mainBundle] pathForResource:@"Dat"ofType:@"plist"]; NSMutableDictionary *dic = [[NSMutableDictionary alloc]initWithContentsOfFile:path]; NSArray *array = [[NSArray alloc]init]; for (id keys in dic) { array = [dic objectForKey:keys]; } *dicには、下記のキー、値が入ってます。(NSLOGで確認しました。) D = ( DAT,DIOP,DSE );... N = ( NET,NW );... Y = (YEA,YAC ); 上記のコードだと、値が全てarrayに格納されませんでした。 なぜか、キーがNの値だけが格納されてしまいます。 全てのキーの値を格納するには、どうしたらよいのでしょうか? よろしくお願いします。

  • iPhoneアプリ開発 ファイル書き込み

    iPhoneアプリ開発につきまして、質問させて頂きます。 csvファイルへのデータの出力を試みているのですが上手くできません。 プログラムとログ内容を以下に記述しました。 「abc」と予め書いてある「hoge.csv」ファイルに「stringaaaaaaaaaaa」を書き込み保存しておきたいのですが、上手くいきません。 ログ内容を見る限り、「abc」が読み込めているので、パスは合っていると思っています。また、writeToFileをしてから読み込むと「stringaaaaaaaaaaa」が読み込めるため、どこかには書き込めているような気がします。 しかし、毎回同じ処理をしても、最初に読み込まれるのは「abc」です。「hoge.csv」をテキストエディタで読み込んでも表示されるのは「abc」です。 また、iPhoneシミュレーターで実行した結果は以下のログ内容なのですが、iPhone実機で動作させると、writeToFileを行ったあとでも「abc」が出力されます。 何か原因を思い当たる方、教えて頂ければ幸いです。 - (void)viewDidLoad { [super viewDidLoad]; [self setTitle:@"Stress Application"]; printf("viewdidload"); NSString *text = [[NSString alloc] initWithFormat:@"stringaaaaaaaaaaaaaaa"]; NSString *_path = [[NSBundle mainBundle] pathForResource:@"hoge" ofType:@"csv"]; //atomicallyは補助ファイルを使ってファイルの破損を防止するかどうか NSLog(@"%@",[NSString stringWithContentsOfFile:_path encoding:NSUTF8StringEncoding error:nil]); [text writeToFile:_path atomically:YES encoding:NSUTF8StringEncoding error:nil]; NSLog(@"%@",[NSString stringWithContentsOfFile:_path encoding:NSUTF8StringEncoding error:nil]); NSLog(@"%@",text); } <ログ内容> 2012-10-31 12:35:10.187 ThinkGearTouch[17182:1a903] FinishLaunching viewdidload2012-10-31 12:35:10.204 ThinkGearTouch[17182:1a903] abc 2012-10-31 12:35:10.212 ThinkGearTouch[17182:1a903] stringaaaaaaaaaaaaaaa 2012-10-31 12:35:10.212 ThinkGearTouch[17182:1a903] stringaaaaaaaaaaaaaaa

  • Objecive-C

    NSDictionary *row1 = [[NSDictionary alloc]initWithObjectsAndKeys:            @"MacBook",@"Name",@"White",@"Color",nil]; NSDictionary *row2 = [[NSDictionary alloc]initWithObjectsAndKeys:        @"MacPro",@"Name",@"Silver",@"Color",nil]; NSArray *array● = [[NSArray alloc]initWithObjects:row1,row2,nil]; これをplistを使って実現させようと思ったのですが、 NSString *path =[[NSBundle mainBundle]pathForResource:@"Celldata" ofType:@"plist"]; NSArray *array○ = [[NSArray alloc]initWithContentsOfFile:path]; *array●と*array○は同様の配列で実現可能ですか? plistに問題があるのでしょうか?。 plistは、下記です。 key Type Value Root Dictionary row1 Dictionary ( 2 items) Name String MacBooc Color String White

  • objectiv-cで困っています。教えてください

    objectiv-cの勉強を始めたばかりです。ネットで調べながら進めているのですが、プロジェクト内のテキストファイルではなく、サーバにあるテキストファイルの内容を読み込み、NSLogに出力しようとしているのですが、うまくいきません。xxxxxxxxxxxの部分にテキストファイルのあるURLを入れています。 -----------------textloadViewController.h------------------------------ #import <UIKit/UIKit.h> @interface textloadViewController : UIViewController @end -----------------textloadViewController.m------------------------------ #import "textloadViewController.h" @interface textloadViewController () @end @implementation textloadViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. NSError *error = nil; NSString *filePath = [[NSBundle mainBundle] pathForResource:@"xxxxxxxxxxx" ofType:@"txt"]; NSString *string = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error]; NSLog(@"%@", string); } @end 外部のテキストファイルを読み込む方法を教えてください。よろしくお願いします。

  • xcode 画像をランダムに並べ順番に押す

    初めてですが質問よろしくお願いします。 iphone開発初心者です。 数字の画像をランダムに5×5に並べ、1から25まで順番に押していく、 というアプリを制作中なのですが行き詰まっています。 現在下記コードのようになっています。 画像を表示まではできたのですが、下記3つ、できればソースコードをお聞きしたいです。 (1)画像25個をランダムに表示する記述がわかりません (今はとりあえずで同じ画像を1つ入れてます。(img1~img25のimg1を代入中)) (2)順番に押していく処理 (3)画像を押された時に音を出したい - (IBAction)image:(id)sender { AudioServicesPlaySystemSound(sound_1); } の部分をうまく入れこめばいいのかと思っていますが、その入れこみ方もわかりません。 AudioToolboxは追加済みです。 どなたかご教授よろしくお願いします。 #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSString *path = [[NSBundle mainBundle] pathForResource:@"btn_1" ofType:@"mp3"]; NSURL *url = [NSURL fileURLWithPath:path]; AudioServicesCreateSystemSoundID((CFURLRef)CFBridgingRetain(url), &sound_1); int yo = 5; for(int i = 0;i<yo; i++){ UIImageView *imageView = [UIImageView new]; imageView.frame = CGRectMake(15+60*i, 100, 60, 60); imageView.image = [UIImage imageNamed:@"img1.png"]; [self.view addSubview:imageView]; } int f = 25; for(int i = 0;i<f; i++){ UIImageView *imageView = [UIImageView new]; imageView.frame = CGRectMake(15+60*(i%5), 100+60*(i/5), 60, 60); imageView.image = [UIImage imageNamed:@"img1.png"]; [self.view addSubview:imageView]; } int rand = arc4random()%f; for(int i = 0; i<f; i++){ if(i == rand){ UIButton*button = [UIButton new]; button.frame = CGRectMake(15+60*(i%5), 100+60*(i/5), 60, 60); [button setImage:[UIImage imageNamed:@"img1.png"] forState:UIControlStateNormal]; [button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchDown]; [self.view addSubview:button]; }else{ UIImageView *imageView = [UIImageView new]; imageView.frame = CGRectMake(15+60*(i%5), 100+60*(i/5), 60, 60); imageView.image = [UIImage imageNamed:@"img1.png"]; [self.view addSubview:imageView]; } } } - (IBAction)image:(id)sender { AudioServicesPlaySystemSound(sound_1); } -(void)buttonTapped{ } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end

専門家に質問してみよう