iOS 9:如何在不显示系统条形图弹出的情况下以编程方式更改音量?

mgv*_*mgv 17 objective-c mpmusicplayercontroller ios mpvolumeview ios9

我必须在iPad上更改音量并使用以下代码:

[[MPMusicPlayerController applicationMusicPlayer] setVolume:0];
Run Code Online (Sandbox Code Playgroud)

但这种不断变化的音量和显示iPad上的系统音量条.如何在不显示音量条的情况下改变声音?

我知道,setVolume:已被弃用,并且每个人都说要使用MPVolumeView.如果这是解决我的问题的唯一方法,那么如何使用MPVolumeView?我没有看到任何MPVolumeView改变声音的方法.
我应该和另一个班级一起使用MPVolumeView吗?

但它最好使用MPMusicPlayerController.

谢谢你的建议!

tru*_*duc 47

2018年,在iOS 11.4上工作

你需要slider.value在一小段延迟后改变.

extension MPVolumeView {
  static func setVolume(_ volume: Float) {
    let volumeView = MPVolumeView()
    let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.01) {
      slider?.value = volume
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

MPVolumeView.setVolume(0.5)
Run Code Online (Sandbox Code Playgroud)

Objective-C版本

  • 在我的情况下,它在iOS 11.4中工作只设置更长的截止日期(例如,DispatchTime.now()+ 0.5) (10认同)
  • 这段代码是有缺陷的——每次设置音量时它都会创建一个全新的“MPVolumeView”UI 对象。我假设需要异步等待,因为系统可能需要一段时间来初始化这个新对象。我建议在启动时创建一次“MPVolumeView”,然后随时使用它,无需等待,也不会浪费电池。 (4认同)
  • @AndreaGorrieri它仍然可以使用0.01延迟而不显示系统条形音箱.好像你可能还有另外一个问题.无论如何,对其他人提出的评论也有同样的问题.谢谢! (3认同)
  • @KerCodex 据我所知,只要初始化`MPVolumeView`(从xib、故事板或以编程方式),就会出现此警告。目前,似乎它仍然可以很好地处理此警告,并且在这种情况下没有人有避免警告的解决方案。 (2认同)

udj*_*jat 16

MPVolumeView有一个滑块,通过更改滑块的值,您可以更改设备音量.我写了一个MPVolumeView扩展来轻松访问滑块:

extension MPVolumeView {
    var volumeSlider:UISlider {
        self.showsRouteButton = false
        self.showsVolumeSlider = false
        self.hidden = true
        var slider = UISlider()
        for subview in self.subviews {
            if subview.isKindOfClass(UISlider){
                slider = subview as! UISlider
                slider.continuous = false
                (subview as! UISlider).value = AVAudioSession.sharedInstance().outputVolume
                return slider
            }
        }
        return slider
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

这是 Swift 中的解决方案。这可能是一个阴暗的,所以我会在我发布时告诉你 Apple 是否批准了这个。同时,这对我来说很好用:

  1. 在你的视图控制器中定义一个 MPVolumeView 和一个可选的 UISlider

    private let volumeView: MPVolumeView = MPVolumeView()
    private var volumeSlider: UISlider?
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在故事板中,定义一个对用户隐藏的视图(height=0 应该可以解决问题),并为其设置一个出口(我们将在此处将其称为 hiddenView)。此步骤仅适用于在更改音量时不显示音量 HUD 的情况(请参阅下面的注释):

    @IBOutlet weak var hiddenView: UIView!
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在 viewDidLoad() 或某个运行一次的 init-y 中,将实际控制音量的 UISlider 捕获到步骤 (1) 中的可选 UISlider 中:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        ...
    
        hiddenView.addSubview(volumeView)
        for view in volumeView.subviews {
            if let vs = view as? UISlider {
                volumeSlider = vs
                break
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 当您想在代码中设置音量时,只需将 volumeSlider?.value 设置为 0.0 和 1.0 之间的任意值,例如用于增加音量:

    func someFunc() {
        if volumeSlider?.value < 0.99 {
            volumeSlider?.value += 0.01
        } else {
            volumeSlider?.value = 1.0
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

重要说明: 此解决方案将阻止 iPhone 的音量 HUD 出现- 无论是在您更改代码中的音量时,还是在用户单击外部音量按钮时。如果您确实想显示 HUD,则跳过所有隐藏的视图内容,并且根本不要将 MPVolumeView 添加为子视图。这将导致 iOS 在音量改变时显示 HUD。


Sen*_*ful 5

extension UIViewController {
  func setVolumeStealthily(_ volume: Float) {
    guard let view = viewIfLoaded else {
      assertionFailure("The view must be loaded to set the volume with no UI")
      return
    }

    let volumeView = MPVolumeView(frame: .zero)

    guard let slider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider else {
      assertionFailure("Unable to find the slider")
      return
    }

    volumeView.clipsToBounds = true
    view.addSubview(volumeView)

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { [weak slider, weak volumeView] in
      slider?.setValue(volume, animated: false)
      DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) { [weak volumeView] in
        volumeView?.removeFromSuperview()
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

用法:

// set volume to 50%
viewController.setVolume(0.5)
Run Code Online (Sandbox Code Playgroud)


Rob*_*art 5

斯威夫特 5 / iOS 13

这是我发现的访问系统音量级别的最可靠的方法。这是基于此处的其他答案,但不会浪费能源,也不需要异步等待。

在初始化期间(例如在 中viewDidLoad),创建一个离屏MPVolumeView

var hiddenSystemVolumeSlider: UISlider!

override func viewDidLoad() {
    let volumeView = MPVolumeView(frame: CGRect(x: -CGFloat.greatestFiniteMagnitude, y:0, width:0, height:0))
    view.addSubview(volumeView)
    hiddenSystemVolumeSlider = volumeView.subviews.first(where: { $0 is UISlider }) as? UISlider
}
Run Code Online (Sandbox Code Playgroud)

然后,在需要时使用隐藏的滑块获取或设置系统音量:

var systemVolume:Float {
    get {
        return hiddenSystemVolumeSlider.value
    }
    set {
        hiddenSystemVolumeSlider.value = newValue
    }
}
Run Code Online (Sandbox Code Playgroud)