Самый простой и наиболее функционально полный способ сделать это, который я нашел при изучении всех источников, упомянутых выше и в других темах: JPSVolumeButtonHandler (Я не участвую, кроме как являюсь пользователем. Но спасибо много ответственным людям!)
РЕДАКТИРОВАТЬ: Выпуск 1.0.2 пришел с некоторыми значительными изменениями / улучшениями. Я оставлю свой предыдущий ответ на 1.0.1 ниже сгиба.
Я поместил пример класса-обертки, который вы можете развернуть как есть или использовать, чтобы, надеюсь, правильно использовать JPSVolumeButtonHandler в отдельном отдельном репозитории Github .
Вот как предполагается использовать обертку (я добавлю это в хранилище, как только доберусь до нее):
Синглтон-класс имеет два флага: isInUse
и isOn
. isInUse
предназначен для установки в каких-то общих настройках приложения и вообще включает и выключает поддержку кнопок.
Таким образом, независимо от каких-либо других значений в классе, если это false
, ничего не произойдет, когда пользователь нажимает кнопку громкости, а реализация максимально старается поддерживать чистоту и не влиять на уровень громкости системы без необходимости. (Прочтите проблему, упомянутую в README, чтобы узнать, что может произойти при первом включении поддержки кнопок.)
Значение isOn
должно быть true
точно на время, необходимое для кнопки. Вы можете включать и выключать его независимо от текущего значения isInUse
.
В каком бы режиме вы ни инициировали действие, которое должно происходить при нажатии кнопки громкости, установите действие следующим образом:
PhysicalButton.shared.action = {/ * сделать что-то * /}
Действие имеет тип () -> Void
. Пока вы не инициализируете действие, ничего не сломается. Просто ничего не случится. Эта защитная функциональность была важна для меня, поскольку представление, использующее поддержку кнопок громкости, будет создано только после настройки поддержки кнопок.
Чтобы увидеть вещи в действии, вы можете скачать приложение , которым я пользуюсь очень быстро и бесплатно. Настройки управляют «поддержкой физических кнопок» в целом. Основной вид секундомера - это тот, который фактически включает обработку кнопок при входе в вид и выключается при выходе из него. Если вы найдете время, вы также найдете важную заметку в меню «Настройки»> «Руководство пользователя»> «Опция: поддержка физических кнопок»:
В исключительных случаях приложение может не получить возможности правильно
выключить управление громкостью за пределами окна секундомера ...
Я добавлю полную заметку в Github README.md. Не стесняйтесь адаптировать и повторно использовать его, если это уместно в вашем случае.
Обстоятельства на самом деле не настолько исключительны, и я не до конца понял, что случилось. Когда пользователь убивает приложение (или вы просто останавливаете его изнутри XCode), когда кнопки громкости включены, поддержка физических кнопок может быть неправильно удалена из ОС. Таким образом, вы можете получить два внутренних экземпляра обработчика, только один из которых вы можете контролировать. Таким образом, каждое нажатие кнопки приводит к двум или даже большему количеству вызовов процедуры действий. В моей оболочке есть некоторый защитный код, чтобы предотвратить слишком быстрый вызов кнопки. Но это только частичное решение. Исправление должно идти в базовый обработчик, который, к сожалению, я все еще слишком мало понимаю, чтобы попытаться исправить все самостоятельно.
СТАРЫЙ, ДЛЯ 1.0.1:
В частности, мой интерес был к решению Swift. Код находится в Objective-C. Чтобы сохранить кому-то какое-то исследование, это все, что я делал, используя Cocoapods (для таких чайников, как я):
- Добавить
pod 'JPSVolumeButtonHandler'
в подфайл
- Выполнить
pod install
в командной строке
- Добавить
#import <JPSVolumeButtonHandler.h>
в файл заголовка моста
Настройка обратных вызовов для кнопок увеличения и уменьшения громкости, например:
let volumeButtonHandler = JPSVolumeButtonHandler(
upBlock: {
log.debug("Volume up button pressed...")
// Do something when the volume up button is pressed...
}, downBlock: {
log.debug("Volume down button pressed...")
// Do something else for volume down...
})
Вот и все. Остальное необязательно.
В моем случае я хотел включить наложение физических нажатий кнопок виртуальными экранными кнопками только для выбранных видов, при этом стараясь максимально блокировать обычные функции кнопок (чтобы пользователь мог запускать музыку в фон и настроить его громкость в остальной части приложения просто отлично). Я закончил в основном синглтон-классом следующим образом:
class OptionalButtonHandler {
static var sharedInstance: OptionalButtonHandler?
private var volumeButtonHandler: JPSVolumeButtonHandler? = nil
private let action: () -> ()
var enabled: Bool {
set {
if !enabled && newValue {
// Switching from disabled to enabled...
assert(volumeButtonHandler == nil, "No leftover volume button handlers")
volumeButtonHandler = JPSVolumeButtonHandler(upBlock: {
log.debug("Volume up button pressed...")
self.action()
}, downBlock: {
log.debug("Volume down button pressed...")
self.action()
})
} else if enabled && !newValue {
log.debug("Disabling physical button...")
// The other way around: Switching from enabled to disabled...
volumeButtonHandler = nil
}
}
get { return (volumeButtonHandler != nil) }
}
/// For one-time initialization of this otherwise singleton class.
static func initSharedInstance(action: () -> ()) {
sharedInstance = OptionalButtonHandler(action: action)
}
private init(action: () -> ()) {
self.action = action
}
}
Здесь есть только одно общее действие для кнопок увеличения и уменьшения громкости. initSharedInstance()
был необходим, потому что мое действие включало ссылки на элемент пользовательского интерфейса (представление), который будет установлен только в некоторой пользовательской точке после запуска приложения.
Разовая настройка:
OptionalButtonHandler.initSharedInstance({
// ...some UI action
})
Включить / отключить выборочно просто так:
OptionalButtonHandler.sharedInstance!.enabled = true // (false)
(Обратите внимание, что моя логика кода гарантирует, что .enabled
никогда не был доступен до initSharedInstance()
.)
Я использую Xcode 7.3 и iOS 9.3.2 на (обязательном!) Тестовом устройстве.
Будем рады узнать, как Apple чувствует себя перегруженной своими драгоценными кнопками громкости. По крайней мере, мое приложение должно быть минимально инвазивным, а использование кнопок действительно имеет смысл. Это не приложение для камеры, но в аналогичных приложениях раньше использовались кнопки физической громкости (даже не очень приятно).