AudioStream Мэтта Галлахера: как обрабатывать всплывающие сообщения контроллера представления

Что ж, это моя самая первая публикация - между этим веб-сайтом, личными блогами и форумами iPhoneDevSDK я всегда мог разобраться во всем самостоятельно. Я занимаюсь разработкой для iOS около пяти месяцев и никогда не просил помощи за пределами Google. Но на этот раз я застрял.

Я успешно внедрил класс AudioStream Мэтта Галагера (мне пришлось удалить ссылку, потому что SO считает, что мой пост является спамом) в свое приложение, и я рад сообщить, что он прекрасно работает. Я' m, используя его в одном контроллере представления, который на самом деле является дочерним по отношению к родительскому представлению в приложении TabBar. Фактически, моя реализация не сильно отличается от примера Мэтта - я изменил только некоторые элементы пользовательского интерфейса.

До этого момента я использовал viewDidDisappear чтобы остановить стример, когда пользователь переключается на другую вкладку. Но недавно я решил, что было бы неплохо, если бы аудиопоток воспроизводился, пока работает приложение, независимо от того, какой вид находится сверху. Это было очень простое изменение, и теперь мой аудиопоток продолжает воспроизводиться независимо от того, где я нахожусь в приложении.

Вот как работает контроллер представления:

  1. У меня есть кнопка воспроизведения и кнопка остановки, лежащие в одном месте. пятно, со скрытой кнопкой Stop.
  2. Когда пользователь нажимает кнопку Play, кнопка Play скрывается, отображение UIActivityIndicatorView (`[streamer isWaiting]`)
  3. Когда начинается воспроизведение потока (`[streamer isPlaying]`), `UIActivityIndicatorView` скрывается, и появляется кнопка Stop
  4. Кроме того, пока` [streamer isPlaying ] `, Я показываю истекшее время (мм: сс) внутри подсказки навигации, которая обновляется каждую секунду

Все вышеперечисленное работает безупречно каждый раз. Если я выйду из представления (либо открыв родительский вид, либо перейдя на другую вкладку), звук будет продолжать воспроизводиться, а это именно то, что я хочу. Но когда я возвращаюсь в представление, пользовательский интерфейс выглядит так, как будто я еще не запустил его (кнопка «Воспроизвести» видна, подсказка навигации скрыта). Если я нажимаю кнопку воспроизведения, я слышу, как второй поток воспроизводится одновременно с первым.

Кажется, что updateProgress остановлен (как self. navigationItem.prompt больше не отображается), и я предполагаю, что playStateChanged "мертв" (не знаю, как это описать).

Я провел часы, просматривая AudioStreamer класс пытается понять, как сохранить контроль над потоком, но я устал. Я надеюсь, что кто-нибудь сможет сказать мне, что мне не хватает.

Как я сказал ранее, мой контроллер представления почти идентичен примеру (см. Гиперссылку выше, поскольку SO все еще предполагает, что я спамер), только с несколькими изменениями, связанными с пользовательским интерфейсом.

Я предполагаю, что краткий вопрос будет следующим: смог ли кто-нибудь реализовать класс AudioSTreamer, открыть его представление, затем вернуться и иметь возможность просмотреть прошедшее время или остановить поток?

РЕДАКТИРОВАТЬ: ниже мой контроллер представления, реализующий AudioStreamer

.h

#import 
#import 
#import 
#import 

@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

8
задан Matthew Clark 20 January 2011 в 04:38
поделиться