- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
过去三天我一直在拔头发来解决这个问题。我检查了很多示例代码,阅读了很多教程,在 stackoverflow 上搜索和检查了很多问题和答案,但我仍然无法解决问题。有几个类似的问题,如 this或 this但他们也没有任何解决方案。
关于我的项目:
我有一个 NIKMasterViewController
和一个 NIKDetailViewController
。在第一个中,我在表格 View 中有一个音频文件列表;选择一行,它会导航到 NIKDetailViewController
,用户可以在其中查看有关文件的一些信息并播放音频文件。我在 NIKMasterViewController
中定义了一个 AVAudioPlayer
属性并将其设置如下:NIKMasterViewController.h
:
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
NIKMasterViewController.m
:
@synthesize audioPlayer;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"showDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
NIKDetailViewController *detailViewController = (NIKDetailViewController *) segue.destinationViewController;
[detailViewController setAudioPlayer:audioPlayer];
[detailViewController setFeedEntry:[[[self feedParser] feedItems] objectAtIndex:indexPath.row]];
} else {
NSLog(@"Segue Identifier: %@", segue.identifier);
}
}
这就是关于 NIKMasterViewController
中的 AVAudioPlayer
的全部内容。现在,在我的 NIKDetailViewController
中,我有了 AVAudioPlayer
的另一个属性:
NIKDetailViewController.h
:
@property (nonatomic, strong) AVAudioPlayer *audioPlayer;
现在在我的 .m 文件中,我有一个名为 streamAudio
的方法,它在 viewDidLoad
中调用以准备音频播放,并且我有一个 if
条件要求检查 audioPlayer
是否为 nill
,如果不是,则 audioPlayer.isPlaying
是否为 true 以便它停止
是播放器,但它从未被调用过,当我导航回 Master VC 以点击另一行以播放另一个文件时,第二个文件开始播放,而第一个文件正在播放,一切都变得困惑。
任何帮助将不胜感激,因为在数小时和数天后仍无法解决此问题后,我几乎要停止编程了!
NIKDetailViewController.m
:
@synthesize audioPlayer;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
selectedItem = [[NSString alloc]init];
}
return self;
}
#pragma mark - Managing the Audio Playback
- (IBAction)togglePlayingState:(id)button
{
//Handle the button pressing
[self togglePlayPause];
}
- (void)playAudio
{
//Play the audio and set the button to represent the audio is playing
[audioPlayer play];
[playPauseButton setImage:[UIImage imageNamed:@"player_pause"] forState:UIControlStateNormal];
}
- (void)pauseAudio
{
//Pause the audio and set the button to represent the audio is paused
[audioPlayer pause];
[playPauseButton setImage:[UIImage imageNamed:@"player_play"] forState:UIControlStateNormal];
}
- (void)togglePlayPause
{
//Toggle if the music is playing or paused
if (!audioPlayer.playing)
{
[self playAudio];
}
else if (audioPlayer.playing)
{
[self pauseAudio];
}
}
- (void)streamAudio
{
currentFileName = [[feedEntry podcastDownloadURL] lastPathComponent];
NSString* documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* path = [documentPath stringByAppendingPathComponent:currentFileName];
NSURL* audioURL = [NSURL fileURLWithPath: path];
if (audioPlayer != nil)
{
if (audioPlayer.isPlaying)
{
[audioPlayer stop]; //THIS IS NEVER CALLED
}
audioPlayer = nil; //THIS IS NEVER CALLED
}
audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:audioURL error:nil];
// Set a timer which keep getting the current music time and update the UISlider in 1 sec interval
playbackTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateSlider) userInfo:nil repeats:YES];
// Set the maximum value of the UISlider
seekSlider.maximumValue = audioPlayer.duration;
currentTime.text = [NSString stringWithFormat:@"%d:%02d", (int)audioPlayer.currentTime / 60, (int)audioPlayer.currentTime % 60, nil];
remainingTime.text = [NSString stringWithFormat:@"%d:%02d", (int)(audioPlayer.duration - audioPlayer.currentTime) / 60, (int)(audioPlayer.duration - audioPlayer.currentTime) % 60, nil];
// Set the valueChanged target
[seekSlider addTarget:self action:@selector(sliderChanged:) forControlEvents:UIControlEventValueChanged];
audioPlayer.delegate = self;
[audioPlayer prepareToPlay]; //Add the audio to the memory.
}
- (void)updateSlider
{
// Update the slider about the music time
seekSlider.value = audioPlayer.currentTime;
}
- (IBAction)sliderChanged:(UISlider *)sender {
// Fast skip the music when user scrolls the slider
[audioPlayer stop];
[audioPlayer setCurrentTime:seekSlider.value];
audioPlayer.delegate = self;
[audioPlayer prepareToPlay];
[audioPlayer play];
}
// Stop the timer when the music is finished (Need to implement the AVAudioPlayerDelegate in the Controller header)
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag {
// Music completed
if (flag) {
[playbackTimer invalidate];
}
}
- (IBAction)forwardAudio:(id)sender
{
int currentTime = [audioPlayer currentTime];
[audioPlayer setCurrentTime:currentTime+10];
}
- (IBAction)rewindAudio:(id)sender
{
int currentTime = [audioPlayer currentTime];
[audioPlayer setCurrentTime:currentTime-10];
}
//Make sure we can recieve remote control events
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)remoteControlReceivedWithEvent:(UIEvent *)event {
//if it is a remote control event handle it correctly
if (event.type == UIEventTypeRemoteControl) {
if (event.subtype == UIEventSubtypeRemoteControlPlay) {
[self playAudio];
} else if (event.subtype == UIEventSubtypeRemoteControlPause) {
[self pauseAudio];
} else if (event.subtype == UIEventSubtypeRemoteControlTogglePlayPause) {
[self togglePlayPause];
}
}
}
#pragma mark - view life cycle
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//Once the view has loaded then we can register to begin recieving controls and we can become the first responder
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
//End recieving events
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
[self resignFirstResponder];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self streamAudio];
//Make sure the system follows our playback status - to support the playback when the app enters the background mode.
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
注意:我曾尝试将 Detail VC 中的属性设置为 weak
但随后,我收到警告,并且属性在我可以播放文件之前被释放.
最佳答案
所以...我终于可以通过创建 audioplayer
的 singleton
来解决这个问题。这是这样的:
NIKMasterViewController
类中删除了所有与 audioPlayer
相关的代码,其中包括 audioPlayer
声明和设置在 prepareForSegue
中。 NIKAudioPlayer
的新类。在 NIKAudioPlayer.h
中:
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
@interface NIKAudioPlayer : NSObject <AVAudioPlayerDelegate>
{
AVAudioPlayer *currentPlayer;
}
@property (nonatomic, strong) AVAudioPlayer *currentPlayer;
+(NIKAudioPlayer *) sharedPlayer;
-(void)playURL:(NSURL*)url;
@end
在 NIKAudioPlayer.m
中:
#import "NIKAudioPlayer.h"
@implementation NIKAudioPlayer
@synthesize currentPlayer;
+(NIKAudioPlayer *) sharedPlayer
{
static NIKAudioPlayer* sharedPlayer;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedPlayer = [[NIKAudioPlayer alloc] init];
});
return sharedPlayer;
}
-(void)playURL:(NSURL*)url
{
[currentPlayer stop];
currentPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:nil];
[currentPlayer prepareToPlay];
}
@end
现在在代码的其他任何地方(在我的例子中是 NIKDetailViewController
)每当我需要播放音频文件时,我从 调用
:sharedPlayer
>NIKAudioPlayer
[[NIKPlayer sharedPlayer] playURL:audioURL];
[[NIKPlayer sharedPlayer].currentPlayer prepareToPlay];
简而言之,将 NIKDetailViewController
中的所有 audioPlayer
替换为 [NIKPlayer sharedPlayer].currentPlayer
,甚至将其转换并使用它无处不在:
audioPlayer = [NIKPlayer sharedPlayer].currentPlayer
关于ios - AVAudioPlayer 始终为 null,其 isPlaying 属性始终为 false。播放时文件混合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20164873/
我有一个 tableview 并且在 tableView 中有多个单元格。 每个单元格都有一个 AVAudioPlayer 我遇到了一个问题。 我不知道如何管理 AVAudioPlayer。 当我播放
我的目标是在视频播放期间播放重复动画,因为我使用的是 VideoView 我想我不妨利用 .isPlaying 方法来解决这个问题 但是 while 循环根本不执行 Floater0 = (I
我在 AVAudioPlayer 类中遇到了一个奇怪的问题。每次我尝试访问它的属性之一时,它们都是空的。 // Get the file path to the song to play. NSSt
使用scene.isPaused和sceneView.isPlaying有什么区别?这些只是从不同地方处理的相同事情吗?是否将其中一个更改为 true,将其他更改为 false,反之亦然? 最佳答案
我正在为 AVAudioPlayer 使用单例,效果很好。 我希望在初始化播放器之前添加一个检查,如果播放器已经在播放,则停止播放器。 我添加了这段代码: SoundPlayer *player =
在 Android 上,我在尝试确定实际播放的铃声时遇到问题(我不是要检测默认铃声,而是实际播放的铃声,因为用户设置的特定铃声可能会有所不同对于特定联系人)。 我正在使用 Ringtone.isPla
我正在 2 部手机上进行测试。在一台设备中,媒体播放器的 isPlaying() 即使在播放时也始终返回 false。但在其他设备(lg optimus Gingerbread )中,isPlayin
我目前正在开发聊天应用程序。在此具有发送语音注释的功能。语音笔记的发送和播放工作正常。但问题是,当我播放语音笔记时,之前播放的语音笔记不会停止..两者一起播放。 这是我播放语音笔记的代码, publ
我刚刚更新到最新版本的 Lottie;我们正在使用 Xamarin 表单,现在我的应用程序崩溃了,因为它找不到 正在播放 循环 谁能告诉我他们被什么取代了? 找不到任何建议替换的内容。 最佳答案 我最
import React from "react"; import { Player } from "@react-native-community/audio-toolkit"; export de
import React from "react"; import { Player } from "@react-native-community/audio-toolkit"; export de
我有一个应用程序,可以在按下按钮时播放声音。 我试图强制 MediaPlayer 在来电时静音,然后以正常音量继续(在空闲模式下)。 我编写了下面的代码来完成此操作,尽管它在下一行的 NullPoin
好的,我在同一 Activity 中获得了两个音轨,因此我为它们使用了两个媒体播放器。我一切正常。唯一的问题是调用 onPause() 时,音频轨道会在 Activity 暂停时暂停。 如果正在播放音
在确定 SKAction.playSoundFileNamed 不仅存在漏洞和泄漏,而且还专门在 IAP 中断期间造成崩溃后,我正在为我们的游戏试验其他音效选项(这不是 OK,Apple)。我们正在尝
当我的 audioPlayer 的 viewDidLoad 时,我正在尝试执行 if 语句。基本上就是说,如果 audioPlayer 正在播放,则暂停它。像这样: override func vie
我发布了我的应用程序,但在 Galaxy Nexus 或 HTC Explorer 等手机上我的应用程序崩溃了。 我在许多手机上进行了测试,应用程序运行完美。 您能解释一下为什么会发生这种情况以及如何
public static MediaPlayer mp=null; public static void playGeneric(int name, final ImageButton button
我正在尝试解决 Android MediaPlayer 的“状态不匹配”错误,当我尝试暂停时,该错误偶尔会在音频播放期间抛出。 如 this question 中所述,Android MediaPla
我有一个包含 AVPlayer 的 UICollectionViewCell。在 cellForItemAtIndexpath 上,我需要检查分配给 AVPlayer 的 URL 是否可播放。我使用以
我有这个: -(ALuint)ID { return self.soundSource->_sourceId; } -(void)play { [self.engine playSound:s
我是一名优秀的程序员,十分优秀!