4

我使用以下代码来检测用户更改的系统音量。

NotificationCenter.default.addObserver(self, selector: #selector(volumeChanged), name: NSNotification.Name(rawValue: "AVSystemController_SystemVolumeDidChangeNotification"), object: nil)

当我更新到 iOS 15 时,我发现这段代码不起作用,但对于任何以前的 iOS 版本它都可以。

我也使用了一个addObserver函数,但没关系。

这是 iOS 15 的错误吗?如果是,我该怎么做才能修复它。

谢谢 :)

4

5 回答 5

12

我挂钩了 MPVolumeControllerSystemDataSource的方法_systemVolumeDidChange并且在iOS 15.0(至少 beta2)中,通知名称已更改为SystemVolumeDidChange,这是新的通知结构:

{
    AudioCategory = "Audio/Video";
    Reason = ExplicitVolumeChange;
    SequenceNumber = 1069;
    Volume = 0;
}

有两点需要注意:

  1. 即使您按一次音量按钮,iOS 15(至少在 beta2 中)的此通知也会被调用两次,但它们的 SequenceNumber 是相等的;
  2. 此通知回调不在主线程上。
于 2021-07-08T05:42:39.373 回答
5

您正在做的事情不受支持,因此如果它不能在所有系统上运行也就不足为奇了。outputVolume正确记录的方法是在音频会话属性上使用 KVO : https ://developer.apple.com/documentation/avfaudio/avaudiosession/1616533-outputvolume

于 2021-07-05T00:53:42.033 回答
1

尝试了 AdamWang 的回答后,我发现您需要创建并保留 MPVolumeView 的实例(但不需要添加到您的视图层次结构中),否则不会发出通知。

于 2021-09-24T04:27:16.033 回答
0

在 iOS15 中,不再调用 @"AVSystemController_SystemVolumeDidChangeNotification" 通知。

改用键值观察。(扩展上面马特的回答)

在您的 ViewController.m 文件中

#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>

@interface ViewController : UIViewController
{
    AVAudioSession *audioSession;
}

@end

在您的 View Controller.m 文件中

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    audioSession = [AVAudioSession sharedInstance];
    [audioSession setActive:YES error:nil];
    [audioSession addObserver:self forKeyPath:@"outputVolume" options:0 context:nil];

}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated]; 

    [audioSession removeObserver:self forKeyPath:@"outputVolume"];
}


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

    CGFloat newVolume = audioSession.outputVolume;
    NSLog(@"newVolume: %f", newVolume);

      //if the volume gets to max or min observer won't trigger
    if (newVolume > 0.9 || newVolume < 0.1) {
        [self setSystemVolume:0.5];
        return;
    }
}

  //set the volume programatically
- (void)setSystemVolume:(CGFloat)volume {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wdeprecated-declarations"
    [[MPMusicPlayerController applicationMusicPlayer] setVolume:(float)volume];
    #pragma clang diagnostic pop
}

您可以使用移出屏幕的 MPVolumeView 隐藏音量滑块。

使用 MPVolumeView 滑块调整音量时隐藏设备音量 HUD 视图

于 2021-10-26T15:09:26.290 回答
0

如果有人突然不明白如何应用 AdamWang 的解决方案,您只需将“ AVSystemController_SystemVolumeDidChangeNotification”替换为“ SystemVolumeDidChange”。

于 2022-01-07T13:03:37.240 回答