Как включить и выключить фонарик в Swift?

Я хотел бы добавить функциональность фонарика в свое приложение в Swift. Как я могу это сделать?


person Lachtan    schedule 29.11.2014    source источник


Ответы (12)


Обновление №1: (torchActive не возвращает ожидаемое значение; возможно, потому, что оно было изменено)

Обновление №2: для Swift 2.0

Чтобы включить или выключить вспышку (а не просто «включить», как в ответе бешеной свиньи), вы можете использовать следующий метод:

func toggleFlash() {
    let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    if (device.hasTorch) {
        do {
            try device.lockForConfiguration()
            if (device.torchMode == AVCaptureTorchMode.On) {
                device.torchMode = AVCaptureTorchMode.Off
            } else {
                do {
                    try device.setTorchModeOnWithLevel(1.0)
                } catch {
                    print(error)
                }
            }
            device.unlockForConfiguration()
        } catch {
            print(error)
        }
    }
}

Я использовал вложенные блоки do-catch, чтобы реализовать предложение Awesomeness из комментариев. Таким образом, даже если try device.setTorchModeOnWithLevel(1.0) не удастся, устройство будет правильно разблокировано для настройки.

Обновление №3: для Swift 4:

(Я немного отредактировал код на свой личный вкус)

func toggleFlash() {
    guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
    guard device.hasTorch else { return }

    do {
        try device.lockForConfiguration()

        if (device.torchMode == AVCaptureDevice.TorchMode.on) {
            device.torchMode = AVCaptureDevice.TorchMode.off
        } else {
            do {
                try device.setTorchModeOn(level: 1.0)
            } catch {
                print(error)
            }
        }

        device.unlockForConfiguration()
    } catch {
        print(error)
    }
}

Оригинальный ответ:

Чтобы включить или выключить вспышку (а не просто «включить», как в ответе бешеной свиньи), вы можете использовать следующий метод:

func toggleFlash() {
    let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    if (device.hasTorch) {
        device.lockForConfiguration(nil)
        let torchOn = !device.torchActive
        device.setTorchModeOnWithLevel(1.0, error: nil)
        device.torchMode = torchOn ? AVCaptureTorchMode.On : AVCaptureTorchMode.Off
        device.unlockForConfiguration()
    }
}
person Lyndsey Scott    schedule 06.12.2014
comment
Я думаю, что вызов setTourchModeOnWithLevel должен находиться в собственном блоке try, чтобы он мог разблокировать устройство для настройки в случае, если что-то пойдет не так. ` do { try device.setTorchModeOnWithLevel(1.0) } catch { device.unlockForConfiguration() } ` - person Awesomeness; 02.12.2015
comment
@Awesomeness Я реализовал ваше предложение, но вместо этого использовал вложенный блок do-catch, так как это на одну строку кода меньше ... Нет необходимости вызывать device.unlockForConfiguration() как внутри, так и вне блока catch setTorchModeOnWithLevel (1.0). - person Lyndsey Scott; 02.12.2015
comment
при быстром нажатии на кнопку фонарика это решение не самое быстрое и срабатывает с небольшой задержкой - person Leon Jakonda; 13.04.2021

Обновленный ответ Swift 4:

func toggleTorch(on: Bool) {
    guard 
        let device = AVCaptureDevice.default(for: AVMediaType.video),
        device.hasTorch
    else { return }

    do {
        try device.lockForConfiguration()
        device.torchMode = on ? .on : .off                    
        device.unlockForConfiguration()
    } catch {
        print("Torch could not be used")
    }
}

Затем, чтобы фактически включить или выключить его, вызовите функцию и передайте логическое значение true или false.

toggleTorch(on: true) of toggleTorch(on: false)

Я получил этот ответ от Взлом с помощью Swift, однако в их примере была ошибка.

Они использовали AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo), но это приводит к ошибке, говорящей, что defaultDevice не существует. Поэтому я изменил его на AVCaptureDevice.default(for: AVMediaType.video)

person Joshua Dance    schedule 20.09.2017
comment
Мне нравится, как был написан этот код. Отлично работал в моем приложении. Просто не забудьте импортировать AVFoundation, чтобы использовать факел. - person Josh; 29.12.2018

Я обновил отличный ответ @Lyndsey Scott для Swift 2.0

let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    if (device.hasTorch) {
        do {
            try device.lockForConfiguration()
            if (device.torchMode == AVCaptureTorchMode.On) {
                device.torchMode = AVCaptureTorchMode.Off
            } else {
                try device.setTorchModeOnWithLevel(1.0)
            }
            device.unlockForConfiguration()
        } catch {
            print(error)
        }
    }
person gpichler    schedule 30.10.2015
comment
Для новичков (таких как я) я хотел бы добавить, что вам нужно включить «импорт AVFoundation» в верхнюю часть быстрого файла контроллера представления. - person dmcknight; 02.01.2016
comment
К вашему сведению, я также обновил свой ответ для Swift 2.0 (ответ, на котором он был основан) несколько месяцев назад, и, в отличие от этого ответа, мой ответ также обрабатывает случай, когда try device.setTorchModeOnWithLevel(1.0) терпит неудачу. - person Lyndsey Scott; 07.03.2016

Свифт 5

Решение уже было написано многими, но я хочу предложить также более лаконичное решение, которое я придумал в своем проекте:

func toggleTorch(on: Bool) {
    guard let device = AVCaptureDevice.default(for: AVMediaType.video) else { return }
    guard device.hasTorch else { print("Torch isn't available"); return }

    do {
        try device.lockForConfiguration()
        device.torchMode = on ? .on : .off
        // Optional thing you may want when the torch it's on, is to manipulate the level of the torch
        if on { try device.setTorchModeOn(level: AVCaptureDevice.maxAvailableTorchLevel.significand) }
        device.unlockForConfiguration()
    } catch {
        print("Torch can't be used")
    }
}

Как упоминалось в комментарии, вы также можете изменить уровень факела, когда он включен, что я считаю очень удобным.

Также импортируйте AVFoundation, чтобы использовать факел.

person Alessandro Francucci    schedule 10.09.2019

Для свифт 3

func toggleFlash() {
    if let device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo), device.hasTorch {
        do {
            try device.lockForConfiguration()
            let torchOn = !device.isTorchActive
            try device.setTorchModeOnWithLevel(1.0)
            device.torchMode = torchOn ? .on : .off
            device.unlockForConfiguration()
        } catch {
            print("error")
        }
    }
}
person Chuy47    schedule 06.12.2016

Вот так:

 func turnTorchOn(){

    let device = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    if device.hasTorch {
        device.lockForConfiguration(nil)
        device.setTorchModeOnWithLevel(1.0, error: nil)
        device.unlockForConfiguration()
    }


}
person mad pig    schedule 29.11.2014

Для xcode 9.1, swift 4 (обновлено, чтобы не падать, если нет факела):

   func toggleFlash() {
    let device = AVCaptureDevice.default(for: AVMediaType.video)

    if (device != nil) {
        if (device!.hasTorch) {
            do {
                try device!.lockForConfiguration()
                    if (device!.torchMode == AVCaptureDevice.TorchMode.on) {
                        device!.torchMode = AVCaptureDevice.TorchMode.off
                    } else {
                        do {
                            try device!.setTorchModeOn(level: 1.0)
                            } catch {
                                print(error)
                            }
                    }

                    device!.unlockForConfiguration()
            } catch {
                print(error)
            }
        }
    }
}
person Lance    schedule 06.12.2017

Решение для Swift 4 с условием факел доступен или нет

 func flashlight() {
            guard let device = AVCaptureDevice.default(for: AVMediaType.video) else{
                return
            }
            if (device.hasTorch) {
                    do {
                        try device.lockForConfiguration()
                        if (device.torchMode == .on) {
                            device.torchMode = .off
                        } else {
                            device.torchMode = .on

                        }
                        device.unlockForConfiguration()
                    } catch {

                        print("Torch could not be used")
                        print(error)
                    }
                }
            else{
                print("Torch is not available")
            }
        }

Решение - это комбинация @Joshua Dance И @Lance

person Anup Gupta    schedule 12.02.2018

Свифт 4.2

if let device = AVCaptureDevice.default(for: AVMediaType.video) {

    if (device.hasTorch) {
        do {
            try device.lockForConfiguration()
            let torchOn = !device.isTorchActive
            try device.setTorchModeOn(level: 1.0)
            device.torchMode = torchOn ? AVCaptureDevice.TorchMode.on : AVCaptureDevice.TorchMode.off
            device.unlockForConfiguration()
        } catch {
            print(error.localizedDescription)
        }
    }
}
person christopher saez    schedule 07.12.2018

Свифт версии 5.2.4

    func toggleFlash(on: Bool ) {
        guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else { return }
        
        do {
            try device.lockForConfiguration()
            
            device.torchMode = on ? .on : .off
            if on {
                try device.setTorchModeOn(level: AVCaptureDevice.maxAvailableTorchLevel)
            }
            
            device.unlockForConfiguration()
        } catch {
            print("Error: \(error)")
        }
    }
person hectorsvill    schedule 28.08.2020

SwiftUI

// TorchState.swift

import SwiftUI
import AVFoundation

class TorchState: ObservableObject {
    
    @Published var isOn: Bool = false {
        didSet {
            toggleTorch(isOn)
        }
    }
    
    private func toggleTorch(_ isOn: Bool) {
        guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else { return }
        
        do {
            try device.lockForConfiguration()
            
            device.torchMode = isOn ? .on : .off
            
            if isOn {
                try device.setTorchModeOn(level: AVCaptureDevice.maxAvailableTorchLevel)
            }
            
            device.unlockForConfiguration()
        } catch {
            print("Error: \(error)")
        }
    }
}

Пример (iOS 14.0):

//ContentView.swift

import SwiftUI

struct ContentView: View {
    @StateObject var torchState = TorchState()
    
    var body: some View {
          Toggle(isOn: $torchState.isOn) {
                Text("Torch")
          }
    }
}
        
person Peter Kreinz    schedule 14.03.2021

Рефакторинг. Свифт 5.4

import AVFoundation


extension UIDevice {
    
    static func toggleFlashLight() {
        guard let device = AVCaptureDevice.default(for: AVMediaType.video),
              device.hasTorch else { return }
        do {
            try device.lockForConfiguration()
            try device.setTorchModeOn(level: 1.0)
            device.torchMode = device.isTorchActive ? .off : .on
            device.unlockForConfiguration()
        } catch {
            assert(false, "error: device flash light, \(error)")
        }
    }

}
person Denis Rybkin    schedule 08.04.2021