衆所周知,ios7已經廢棄了MPMusicPlayerControllerios
ios7如下使用[[MPMusicPlayerController applicationMusicPlayer] setVolume:value];app
那麼ios7以上呢?使用MPVolumeView。ide
然而MPVolumeView有其侷限性,MPVolumeView的subviews中的MPVolumeSlider的value值,即系統音量值(取值[0,1])post
當我第一次在viewWillAppear的時候,獲取其中的MPVolumeSlider,會獲取不到;atom
因此嘗試在viewDidAppear,這一次很開心,獲取到了;spa
然而,以後發如今某些設備的一倍屏下,仍然獲取不到,或第一次獲取不到,第二次能夠獲取到code
因此,本文采用將MPVolumeView加入window.subview的形式,提早將MPVolumeView加入視圖,做爲全局的一個視圖。server
這樣的作法有助於分離音量與主業務邏輯,充分解耦blog
KEVolumeUtil.h
#define Volume_Change_Notification @"Volume_Change_Notification" @interface KEVolumeUtil : NSObject @property (nonatomic,assign) CGFloat volumeValue; + (KEVolumeUtil *) shareInstance; -(void)loadMPVolumeView; - (void)registerVolumeChangeEvent; - (void)unregisterVolumeChangeEvent; @end
KEVolumeUtil.m
#import "KEVolumeUtil.h" #import "KEAppDelegate.h" #import <MediaPlayer/MediaPlayer.h> #import <AVFoundation/AVFoundation.h> @interface KEVolumeUtil() @property (nonatomic, strong) MPVolumeView *mpVolumeView; @property (nonatomic, strong) UISlider *slider; @end @implementation KEVolumeUtil @synthesize volumeValue = _volumeValue; #pragma mark public methods +(KEVolumeUtil *) shareInstance { static KEVolumeUtil *instance = nil; static dispatch_once_t predicate; dispatch_once (&predicate, ^{ instance = [[self alloc] init]; }); return instance; } - (void) loadMPVolumeView { UIWindow *window = [KEAppDelegate globalAppDelegate].window; [window addSubview:self.mpVolumeView]; [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:NULL]; } - (void)registerVolumeChangeEvent { NSError *error; [[AVAudioSession sharedInstance] setActive:YES error:&error]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(volumeChangedNotification:) name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil]; } - (void)unregisterVolumeChangeEvent { [[NSNotificationCenter defaultCenter] removeObserver:self name:@"AVSystemController_SystemVolumeDidChangeNotification" object:nil]; } #pragma mark private methods -(void) generateMPVolumeSlider { for (UIView *view in [self.mpVolumeView subviews]){ if ([view.class.description isEqualToString:@"MPVolumeSlider"]){ self.slider = (UISlider*)view; break; } } } #pragma mark setters -(void) setVolumeValue:(CGFloat) newValue { _volumeValue = newValue; //確保self.slider != nil if (!self.slider) { [self generateMPVolumeSlider]; } self.slider.value = newValue; } #pragma mark getters -(CGFloat) volumeValue { //確保self.slider != nil if (!self.slider) { [self generateMPVolumeSlider]; } return self.slider.value; } -(MPVolumeView *) mpVolumeView { if (!_mpVolumeView) { _mpVolumeView = [[MPVolumeView alloc] initWithFrame:CGRectMake(0, 50, 100, 100)]; _mpVolumeView.hidden = YES; } return _mpVolumeView; } #pragma mark notification - (void)volumeChangedNotification:(NSNotification *)notification { NSDictionary *userInfo = notification.userInfo; float value = [[userInfo objectForKey:@"AVSystemController_AudioVolumeNotificationParameter"] floatValue]; self.volumeValue = value; [[NSNotificationCenter defaultCenter] postNotificationName:Volume_Change_Notification object:nil]; } @end