Память и цикл while true в Свифт


#1

Здравствуйте, я использую этот код while true {
AudioServicesPlaySystemSound(SystemSoundID(1520))
} для создания бесконечной вибрации. При нажатии на кнопку приложение начинает вибрировать но через какое-то время вылетает и выдаёт ошибку The app “massegere1” on iPhone (Егор) quit unexpectedly.
Message from debugger: Terminated due to memory issue как её исправить. И ещё один вопрос: как остановить эту вибрацию при повторном нажатии на кнопку?
Помогите пожалуйста :pray:
Заранее спасибо


#2

Здравствуйте.
Нужно быть очень осторожным с бесконечными циклами. В вашем случае, вы каждую итерацию даёте устройству команду на проигрывание звука - итерации проходят очень быстро, проигрываемых одновременно звуков становится очень много, можете посмотреть в xCode, как увеличивается потребление памяти вашим приложением)
Лучше использовать метод AudioServicesPlaySystemSoundWithCompletion, который может выполнять код после завершения своей работы - и в нём повторно запустить вибрацию, если это необходимо.
А чтобы включать/выключать вибрацию по кнопке, хранить состояние в переменной типа Bool, например так:

private var vibroEnabled = false

@IBAction func buttonAction(_ sender: UIButton) {
    vibroEnabled = !vibroEnabled

    if vibroEnabled {
        startVibration()
    }
}

private func startVibration() {
    AudioServicesPlaySystemSoundWithCompletion(SystemSoundID(1520)) {
        if self.vibroEnabled {
            self.startVibration()
        }
    }
}

#3

Спасибо это и правда работает. Только я там воспроизвожу вибрацию.
У меня шесть кнопок с вибрацией не подскажите как сделать так чтоб при работе одной кнопки можно было переключится на другую и предидущая полностью остановила свой цикл?
В данный момент при работе одной кнопки я нажимаю на вторую и да она начинает выполнять свой код но чтоб полностью остановить вибрацию надо нажать сначала на вторую а затем уже на первую и только при этом вибрация полностью остановится


#4

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


#6

А как это можно написать в данном коде?


#7

Создайте енум для ваших вибраций

enum Vinbration: Int {
    case vibro1 = 1520
    case vibro2 = ...
}

В вашем VC создайте переменную, которая будет хранить тип вибрации
var selectedVibro: Vibration?

Далее при нажатии на ваши кнопки, присваивайте этой переменной свой тип вибрации

func btn1Click() {
    if selectedVibro == .vibro1 { selectedVibro = nil }
    else selectedVibro = .vibro1

    startVibration()
}
func btn2Click() {
    if selectedVibro == .vibro2 { selectedVibro = nil }
    else selectedVibro = .vibro2

    startVibration()
}

Ну а дальше уже вызывайте метод который будет проверять нужно ли запускать вибрацию или остановиться. В этом методе уже будете проверять переменную selectedVibro, что бы она не была пустая. А что бы получить нужный код вибрации selectedVibro.rawValue.

func startVibration() {
    guard let selectedVibro else { return }
    AudioServicesPlaySystemSoundWithCompletion(SystemSoundID(selectedVibro.rawValue)) {
            self.startVibration()
    }
}

#8

При использовании данного кода вылазят данные ошибки как их убрать? Может я делаю что то не так?


#9

Тут очень много ошибок!
1 - let selectedVibro: Vibration? // Замени на var
2 - Вынеси функции btn1Click и startVibration за пределы экшена
3 - В функции btn1Click не хватает закрывающей скобки “}”
4 - В функции startVibration guard let vibrationType = selectedVibro else { return }


#10


#11

Следите за скобками
И рекомендую пройти основы программирования

Думаю так будет проще


#12

Спасибо большое. Всё заработало