Matt Gallagher的AudioStream:如何处理视图控制器pop

Mat*_*ark 8 iphone objective-c audiostreamer ios

嗯,这是我的第一篇文章 - 在这个网站,个人博客和iPhoneDevSDK论坛之间,我一直能够自己解决问题.我已经为iOS开发了大约五个月,并且从未在Google之外寻求过帮助.但是这一次,我被困住了.

我已经成功实现了Matt Galagher的AudioStream类(必须删除链接,因为SO假定我的帖子是垃圾邮件)到我的应用程序中,我很高兴地报告它工作得很漂亮.我在一个视图控制器中使用它,它实际上是TabBar应用程序中父视图的子视图.事实上,我的实现与Matt的例子没有太大的不同- 我只改变了一些UI元素.

到目前为止,viewDidDisappear当用户切换到另一个选项卡时,我一直在使用停止拖缆.但最近我决定,只要应用程序正在运行,就可以让音频流播放,无论顶视图是什么.这是一个非常简单的变化,现在我的音频流继续播放,无论我在应用程序中的哪个位置.

以下是视图控制器的工作方式:

  1. 我有一个播放按钮和一个停止按钮,位于同一位置,隐藏了停止按钮.
  2. 当用户按下播放按钮时,播放按钮隐藏,显示UIActivityIndi​​catorView(`[streamer isWaiting]`)
  3. 当流开始播放时(`[streamer isPlaying]`),隐藏了'UIActivityIndi​​catorView`,并出现一个停止按钮
  4. 此外,当`[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
Run Code Online (Sandbox Code Playgroud)

.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
Run Code Online (Sandbox Code Playgroud)

Mat*_*ark 0

事实证明,我只需要重新思考如何分配和推送视图。“更多”选项卡显示一个表格视图,每个单元格代表一个子视图,当选择该单元格时将推送该子视图。我更改了此视图以分配其中的所有子视图viewDidLoad,然后只需执行内部推送didSelectRowAtIndexPath,并释放 中的子视图dealloc

这完美解决了我的问题。感谢杰森·可可让一切顺利进行。