8

ええと、これは私の初めての投稿です。この Web サイト、個人のブログ、iPhoneDevSDK フォーラムの間で、私は常に自分で物事を理解することができました。私は約 5 か月間 iOS 向けの開発を行ってきましたが、Google 以外に支援を求めたことは一度もありません。しかし、今回は行き詰まりました。

Matt Galagher の AudioStream クラス (SO は私の投稿がスパムであると想定しているため、リンクを削除する必要がありました) をアプリに正常に実装しました。私はそれを 1 つのビュー コントローラーで使用していますが、これは実際には TabBar アプリの親ビューの子です。実際、私の実装はMatt の例と大差ありません。いくつかの UI 要素を変更しただけです。

これまでviewDidDisappearは、ユーザーが別のタブに切り替えたときにストリーマーを停止するために使用していました。しかし最近、どのビューが一番上にあるかに関係なく、アプリが実行されている限りオーディオ ストリームを再生できるようにする方が賢明だと判断しました。これは非常に単純な変更で、今ではアプリのどこにいてもオーディオ ストリームが再生され続けています。

ビューコントローラーの仕組みは次のとおりです。

  1. 再生ボタンと停止ボタンを同じ場所に配置し、停止ボタンを非表示にします。
  2. ユーザーが再生ボタンを押すと、再生ボタンが非表示になり、UIActivityIndi​​catorView (`[streamer isWaiting]`) が表示されます。
  3. ストリームの再生が開始されると (`[streamer isPlaying]`)、`UIActivityIndi​​catorView` が非表示になり、停止ボタンが表示されます。
  4. また、「[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
4

1 に答える 1

0

ビューを割り当ててプッシュする方法を再考する必要があったことがわかりました。[その他] タブにはテーブル ビューが表示され、各セルは、そのセルが選択されたときにプッシュされる子ビューを表します。このビューを変更して、すべての子ビューを 内に割り当ててからviewDidLoad、 内でプッシュを実行し、内の子ビューdidSelectRowAtIndexPathを解放しますdealloc

これは私の問題を完全に解決します。ボールを転がしてくれたジェイソン・ココに感謝します。

于 2011-01-20T15:20:55.977 に答える