ええと、これは私の初めての投稿です。この Web サイト、個人のブログ、iPhoneDevSDK フォーラムの間で、私は常に自分で物事を理解することができました。私は約 5 か月間 iOS 向けの開発を行ってきましたが、Google 以外に支援を求めたことは一度もありません。しかし、今回は行き詰まりました。
Matt Galagher の AudioStream クラス (SO は私の投稿がスパムであると想定しているため、リンクを削除する必要がありました) をアプリに正常に実装しました。私はそれを 1 つのビュー コントローラーで使用していますが、これは実際には TabBar アプリの親ビューの子です。実際、私の実装はMatt の例と大差ありません。いくつかの UI 要素を変更しただけです。
これまでviewDidDisappear
は、ユーザーが別のタブに切り替えたときにストリーマーを停止するために使用していました。しかし最近、どのビューが一番上にあるかに関係なく、アプリが実行されている限りオーディオ ストリームを再生できるようにする方が賢明だと判断しました。これは非常に単純な変更で、今ではアプリのどこにいてもオーディオ ストリームが再生され続けています。
ビューコントローラーの仕組みは次のとおりです。
- 再生ボタンと停止ボタンを同じ場所に配置し、停止ボタンを非表示にします。
- ユーザーが再生ボタンを押すと、再生ボタンが非表示になり、UIActivityIndicatorView (`[streamer isWaiting]`) が表示されます。
- ストリームの再生が開始されると (`[streamer isPlaying]`)、`UIActivityIndicatorView` が非表示になり、停止ボタンが表示されます。
- また、「[streamer isPlaying]」の間、1 秒ごとに更新されるナビゲーション プロンプト内に経過時間 (mm:ss) を表示しています。
上記のすべてが毎回完璧に機能します。ビューを離れると(親ビューにポップするか、別のタブに移動して)、オーディオは再生され続けます。これはまさに私が望んでいることです。しかし、ビューに戻ると、UI はまだ開始していないかのように表示されます ([再生] ボタンが表示され、ナビゲーション プロンプトが非表示になっています)。再生ボタンを押すと、最初のストリームと同時に 2 番目のストリームが再生されます。
updateProgress
は停止したようで (表示されself.navigationItem.prompt
なくなったため)、playbackStateChanged
は「死んでいる」と推測しています (どのように説明すればよいかわかりません)。
ストリームの制御を維持する方法を見つけようとして AudioStreamer クラスをふるいにかけるのに何時間も費やしましたが、疲れ果てています。誰かが私に欠けているものを教えてくれることを願っています。
前に述べたように、私のビュー コントローラーは例とほとんど同じです (SO は私がまだスパマーであると想定しているため、上記のハイパーリンクを参照してください)。UI 関連の変更はわずかです。
簡単な質問は次のようになると思います: AudioSTreamer クラスを実装し、そのビューをポップしてから戻ってきて、経過時間を表示したり、ストリームを停止したりできる人はいますか?
編集: 以下は、AudioStreamer を実装する私のビュー コントローラーです。
.h
#import <UIKit/UIKit.h>
#import <QuartzCore/CoreAnimation.h>
#import <MediaPlayer/MediaPlayer.h>
#import <CFNetwork/CFNetwork.h>
@class AudioStreamer;
@interface RadioViewController : UIViewController
{
IBOutlet UIButton *playButton;
IBOutlet UIButton *stopButton;
IBOutlet UIActivityIndicatorView *waitIndicator;
AudioStreamer *streamer;
NSTimer *progressUpdateTimer;
BOOL shouldAutoStop;
}
- (IBAction)play;
- (IBAction)stop;
- (void)createStreamer;
- (void)destroyStreamer;
- (void)updateProgress:(NSTimer *)aNotification;
- (void)checkWiFi;
@end
.m
#import "AudioStreamer.h"
#import "ServerCheck.h"
#import "RadioViewController.h"
@implementation RadioViewController
- (void)viewDidLoad
{
[[self navigationItem] setTitle:@"WXK33 162.550"];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkWiFi) name:UIApplicationDidBecomeActiveNotification object:nil];
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated
{
[self performSelector:@selector(checkWiFi)];
[super viewDidAppear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
//[self performSelector:@selector(stop)];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil];
[super viewDidDisappear:animated];
}
- (void)createStreamer
{
if ([ServerCheck serverReachable:@"audiostream.wunderground.com"])
{
if (streamer)
{
return;
}
[self destroyStreamer];
NSURL *url = [NSURL URLWithString:@"http://audiostream.wunderground.com/MaffooClock/San_Angelo.mp3"];
streamer = [[AudioStreamer alloc] initWithURL:url];
progressUpdateTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateProgress:) userInfo:nil repeats:YES];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackStateChanged:) name:ASStatusChangedNotification object:streamer];
}
else
{
[[self navigationController] popViewControllerAnimated:YES];
}
}
- (IBAction)play
{
[self createStreamer];
[waitIndicator startAnimating];
[streamer start];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
- (IBAction)stop
{
self.navigationItem.prompt = nil;
[streamer stop];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
- (void)playbackStateChanged:(NSNotification *)aNotification
{
if ([streamer isWaiting])
{
[playButton setHidden:YES];
[stopButton setHidden:YES];
[waitIndicator startAnimating];
}
else if ([streamer isPlaying])
{
[playButton setHidden:YES];
[stopButton setHidden:NO];
[waitIndicator stopAnimating];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
else if ([streamer isIdle])
{
[self destroyStreamer];
[playButton setHidden:NO];
[stopButton setHidden:YES];
[waitIndicator stopAnimating];
}
}
- (void)updateProgress:(NSTimer *)updatedTimer
{
if (streamer.bitRate > 0.0)
{
double progress = streamer.progress;
double minutes = floor(progress/60);
double seconds = trunc(progress - (minutes * 60));
self.navigationItem.prompt = [NSString stringWithFormat:@"Elapsed: %02.0f:%02.0f",minutes,seconds];;
if (shouldAutoStop && progress > 600)
[self performSelector:@selector(stop)];
}
else
{
self.navigationItem.prompt = nil;
}
}
- (void) checkWiFi
{
if (![ServerCheck wifiAvailable])
{
LogInfo(@"No Wi-Fi");
NSString * messageTitle = @"Notice";
NSString * messageText = @"It appears that you do not have an active Wi-Fi connection. Listening to streaming audio via cellular data may incurr additional data charges. Streaming will automatically stop after 10 minutes.";
UIAlertView *errorAlert = [[UIAlertView alloc] initWithTitle:messageTitle message:messageText delegate:self cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
[errorAlert show];
[errorAlert release];
shouldAutoStop = YES;
}
else
shouldAutoStop = NO;
}
- (void)destroyStreamer
{
if (streamer)
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:ASStatusChangedNotification object:streamer];
[progressUpdateTimer invalidate];
progressUpdateTimer = nil;
[streamer stop];
[streamer release], streamer = nil;
}
}
- (void)dealloc
{
[self destroyStreamer];
if (progressUpdateTimer)
{
[progressUpdateTimer invalidate], progressUpdateTimer = nil;
}
[super dealloc];
}
@end