Исчезновение (анимация) громкости с помощью MPMediaPlayer Swift 4

Я использую Xcode 10+, Swift 4 и нацелен на iOS 11.4+ с MPMediaPlayer.

Я хотел бы программно уменьшить громкость проигрывателя (как это делает Apple, когда вы выходите из своего музыкального проигрывателя). Кроме того, я не хочу ничего видеть (например, дисплей VolumeView), когда он работает.

Похоже, что все программные регуляторы громкости устарели.

Я прочитал много связанных сообщений и создал эту функцию, которая имеет несколько проблем:

@objc func fadeVolume(){
    var sliderView = UISlider()
    //let volumeView = MPVolumeView(frame: CGRect.init(x: self.view.frame.maxX, y: self.view.frame.maxY, width: 0, height: 0))
    let volumeView = MPVolumeView(frame: .zero)
    volumeView.clipsToBounds = true
    volumeView.showsRouteButton = false
    //volumeView.isHidden = true
    volumeView.alpha = 0.001
    for subview in volumeView.subviews {
        if let slider = subview as? UISlider {
            sliderView = slider
            break
        }
    }
    self.view.addSubview(volumeView)
    volumeView.didMoveToSuperview()

    let current:Float = AVAudioSession.sharedInstance().outputVolume
    print("slider value: \(current)")
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.1) {
        UIView.animate(withDuration: 0.4, animations: {
            sliderView.setValue(0.0, animated: false)
        }, completion: { finished in
            // If either one of these is uncommented, the VolumeView will display.
            // However, without removing from superview, the VolumeView stays hidden even when I use the phone volume buttons.
            volumeView.removeFromSuperview()
            //volumeView.alpha = 1.0
        })
    }
}

Первая проблема: отображение VolumeView отображается на экране. Я пробовал использовать разные кадры, менять альфу и т. д. Как будто анимация никогда не происходит и идет прямо к блоку завершения.

Вторая проблема: VolumeView действительно необходимо удалить из супервизора, иначе он останется скрытым, даже когда я использую кнопки громкости телефона. Его следует скрывать только во время выполнения этой функции.

Третья проблема: блок анимации ничего не делает. Громкость просто мгновенно перейдет от начальной точки к 0 - без затухания.

Четвертая проблема: я не проверял это, но я предполагаю, что это не будет работать, когда приложение находится в фоновом режиме. Таким образом, идея использовать это для уменьшения громкости при выходе из приложения может не сработать.

Любая идея, как уменьшить громкость, не отображая ничего на экране? Для ответа не обязательно использовать MPVolumeView, но мне нужно, чтобы он работал с MPMediaPlayer и при выходе из приложения.

РЕДАКТИРОВАТЬ: Ниже приведен мой модифицированный код, который уменьшит громкость, однако проблема с возможностью сделать это, когда мое приложение завершается, все еще существует. Я могу вызвать этот код из appWillTerminate, однако он не запускается полностью, так как приложение завершается до того, как оно сможет пройти весь путь.

// Public in ViewController Class:
let volumeView = MPVolumeView()
var sliderView = UISlider()
var currentVolume:Float = 0

//This called by a notification:
    @objc func fadeVolume(){
        // A lot of other posts use these to hide the volume view however I only needed the alpha change
        //volumeView.clipsToBounds = true
        //volumeView.showsRouteButton = false
        //volumeView.isHidden = true
        //print("volume alpha \(volumeView.alpha)")
        volumeView.alpha = 0.001
        self.view.addSubview(volumeView)
        volumeView.didMoveToSuperview()
        if let view = volumeView.subviews.first as? UISlider {
            sliderView = view
        }
        print("slider value: \(sliderView.value)")
        currentVolume = sliderView.value
        changeVolumeSlowly()
    }
    @objc func changeVolumeSlowly(){
        sliderView.value = sliderView.value - 0.1
        print("\(sliderView.value)")
        if sliderView.value > 0 {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
                self?.changeVolumeSlowly()
            }
        } else {
            myMP.pause()
            myMP.stop()
            //reset
            // Since the volumeView is 'global' to the app, if you do not change
            // it back to the previous volume and make it visible you won't see it unless you restart your app.
            //Unfortunately these cause the volume view to flash onscreen
            volumeView.alpha = 1.0
            sliderView.value = currentVolume
            volumeView.removeFromSuperview()
        }
    }

person wayneh    schedule 21.12.2018    source источник


Ответы (1)


Сделайте свою переменную UISLider общедоступной и используйте эту функцию, чтобы уменьшить громкость звука.

@objc func changeVolumeSlowly(){
    sliderView.value = sliderView.value - 0.1
    print("\(sliderView.value)")
    if sliderView.value > 0 {
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in
            self?.changeVolumeSlowly()
        }
    }
}
person Shahzaib Qureshi    schedule 14.02.2019
comment
Я попробовал ваш код и обнаружил, что он будет работать, если я также объявлю VolumeView общедоступным и изменю порядок нескольких действий. Однако я не могу заставить это работать во время applicationWillTerminate (часть моей исходной проблемы). Я отредактировал свой пост, чтобы отразить изменения до сих пор. - person wayneh; 16.02.2019