就是一个单例的设计,并没有多大难度。我是用了一个字典来装播放过的歌曲了,这样如果是暂停了,然后再开始播放,就直接在缓存中加载即可。但是如果不注意,在 stopMusic:(NSString *)fileName 这个方法里面,不从字典中移除掉已经停止播放的歌曲,那么你下再播放这首歌的时候,就会在原先播放的进度上继续播放。在编码过程中,我就遇到了这个Bug,然后发现,在切换歌曲(上一曲、下一曲)的时候,我调用的是stopMusic方法,但由于我没有从字典中将它移除,而导致它总是从上一次的进度开始播放,而不是从头开始播放。
如果在真机上想要后台播放歌曲,除了在appDelegate以及plist里面做相应操作之外,还得将播放模式设置为:AVAudioSessionCategoryPlayback。特别需要注意这里,我在模拟器上调试的时候,没有设置这种模式也是可以进行后台播放的,但是在真机上却不行了。后来在StackOverFlow上找到了对应的答案,需要设置播放模式。
这个单例类,在整个demo中是至关重要的,要保证它是没有错误的,所以我写了这个类的XCTest进行单元测试,代码如下:
#import <XCTest/XCTest.h>
#import "ZYAudioManager.h"
#import <AVFoundation/AVFoundation.h>
@interface ZYAudioManagerTests : XCTestCase
@property (nonatomic, strong) AVAudioPlayer *player;
@end
static NSString *_fileName = @"10405520.mp3";
@implementation ZYAudioManagerTests
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
/**
* 测试是否为单例,要在并发条件下测试
*/
- (void)testAudioManagerSingle
{
NSMutableArray *managers = [NSMutableArray array];
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
ZYAudioManager *tempManager = [[ZYAudioManager alloc] init];
[managers addObject:tempManager];
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
ZYAudioManager *tempManager = [[ZYAudioManager alloc] init];
[managers addObject:tempManager];
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
ZYAudioManager *tempManager = [[ZYAudioManager alloc] init];
[managers addObject:tempManager];
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
ZYAudioManager *tempManager = [[ZYAudioManager alloc] init];
[managers addObject:tempManager];
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
ZYAudioManager *tempManager = [[ZYAudioManager alloc] init];
[managers addObject:tempManager];
});
ZYAudioManager *managerOne = [ZYAudioManager defaultManager];
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[managers enumerateObjectsUsingBlock:^(ZYAudioManager *obj, NSUInteger idx, BOOL * _Nonnull stop) {
XCTAssertEqual(managerOne, obj, @"ZYAudioManager is not single");
}];
});
}
/**
* 测试是否可以正常播放音乐
*/
- (void)testPlayingMusic
{
self.player = [[ZYAudioManager defaultManager] playingMusic:_fileName];
XCTAssertTrue(self.player.playing, @"ZYAudioManager is not PlayingMusic");
}
/**
* 测试是否可以正常停止音乐
*/
- (void)testStopMusic
{
if (self.player == nil) {
self.player = [[ZYAudioManager defaultManager] playingMusic:_fileName];
}
if (self.player.playing == NO) [self.player play];
[[ZYAudioManager defaultManager] stopMusic:_fileName];
XCTAssertFalse(self.player.playing, @"ZYAudioManager is not StopMusic");
}
/**
* 测试是否可以正常暂停音乐
*/
- (void)testPauseMusic
{
if (self.player == nil) {
self.player = [[ZYAudioManager defaultManager] playingMusic:_fileName];
}
if (self.player.playing == NO) [self.player play];
[[ZYAudioManager defaultManager] pauseMusic:_fileName];
XCTAssertFalse(self.player.playing, @"ZYAudioManager is not pauseMusic");
}
@end










