嗯,这是我有史以来的第一篇文章——在这个网站、个人博客和 iPhoneDevSDK 论坛之间,我总是能够自己解决问题。我已经为 iOS 开发了大约五个月,从未在 Google 之外寻求帮助。但这一次,我被困住了。
我已经成功地在我的应用程序中实现了 Matt Galagher 的 AudioStream 类(必须删除链接,因为 SO 假定我的帖子是垃圾邮件),我很高兴地报告它运行良好。我在一个视图控制器中使用它,它实际上是 TabBar 应用程序中父视图的子视图。事实上,我的实现与Matt 示例中的实现并没有太大区别——我只是更改了一些 UI 元素。
到目前为止,viewDidDisappear
当用户切换到另一个选项卡时,我一直在使用停止流媒体。但最近我决定,只要应用程序正在运行,就可以让音频流播放,无论顶部是什么视图。这是一个非常简单的更改,现在无论我在应用程序的哪个位置,我的音频流都会继续播放。
以下是视图控制器的工作原理:
- 我有一个播放按钮和一个停止按钮放在同一个位置,停止按钮隐藏。
- 当用户按下播放按钮时,播放按钮隐藏,显示 UIActivityIndicatorView (`[streamer isWaiting]`)
- 当流开始播放时(`[streamer isPlaying]`),`UIActivityIndicatorView` 被隐藏,并出现一个停止按钮
- 此外,在“[streamer isPlaying]”时,我在导航提示中显示经过的时间 (mm:ss),它每秒更新一次
上述所有工作每次都完美无缺。如果我离开视图(通过弹出到父视图或导航到另一个选项卡),音频将继续播放,这正是我想要的。但是当我返回视图时,UI 看起来好像我还没有启动它(播放按钮可见,导航提示被隐藏)。如果我按下播放按钮,我会听到第二个流与第一个流同时播放。
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