SwiftUI 예제: 아이폰 손전등(Flashlight) 만들기 (카메라 플래시 + 화면 밝기 강제 조정 및 복구)
SwiftUI 예제: 아이폰 손전등(Flashlight) 만들기 (카메라 플래시 + 화면 밝기 강제 조정 및 복구)
소개
아이폰 손전등에는 다음 3가지 기능이 필요합니다.
- 아이폰 후면 카메라에 달려있는 플래시(Swift에서는
torch라고 함)의 밝기 조절
- (옵션) 디스플레이 전면의 화면 밝기 조정
- (옵션)
scenePhase를 통한 백그라운드 시 화면 밝기 원래대로 돌려놓기
모든 기능은 실제 아이폰 기기에서만 실행할 수 있습니다.
참고) 손전등 앱(정확히 말하면 손전등 기능만 있는 앱)은 최신 앱 스토어 심사 지침에서 스팸 앱으로 분류됩니다.
방법
1. 플래시 켜기 및 밝기 조절
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import AVFoundation
private func setTorch(_ torchBrightness: Float) {
guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else {
return
}
do {
try device.lockForConfiguration()
try device.setTorchModeOn(level: torchBrightness)
// 참고: 플래시 끄기
// device.torchMode = .off
device.unlockForConfiguration()
} catch {
print(#function, error.localizedDescription)
}
}
2. (옵션) 디스플레이 전면의 화면 밝기 조정
1
2
3
private func setBrightness(_ displayBrightness: CGFloat) {
UIScreen.main.brightness = displayBrightness
}
3. (옵션) scenePhase를 통한 백그라운드 시 화면 밝기 원래대로 돌려놓기
앱을 켜면 화면 밝기가 최대가 되어도 앱을 끄거나 백그라운드 모드로 나가면 앱을 실행하기 이전의 화면 밝기로 되돌아가야 합니다.
앱의 상태는 scenePhase로 감지할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Environment(\.scenePhase) var scenePhase
// ... //
.onChange(of: scenePhase) { scenePhase in
switch scenePhase {
case .background:
print("App is in background")
case .inactive:
print("App is inactive")
case .active:
// print("App is active")
@unknown default:
break
}
}
앱이 활성화된 단계(active)에서 화면 밝기 값을 미리 저장해놓고, 앱이 백그라운드 모드가 되면(background) 미리 저장했던 밝기값으로 되돌려 놓습니다. (전체 코드의 outsideDisplayBrightness 상태 변수 참고)
전체 코드
Swift Playground App 프로젝트를 생성한 뒤 ContentView를 아래와 같이 채웁니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import SwiftUI
import AVFoundation
struct ContentView: View {
private let DEBUG_MODE: Bool = false
@Environment(\.scenePhase) var scenePhase
@State var outsideDisplayBrightness: CGFloat = 0.5
@State var displayBrightness: CGFloat = 1.0 {
didSet {
guard displayBrightness <= 1 && displayBrightness >= 0 else {
return
}
setBrightness(displayBrightness)
}
}
@State var torchBrightness: Float = 1.0 {
didSet {
guard torchBrightness <= 1.0 else {
torchBrightness = 1.0
return
}
guard torchBrightness >= 0.0 else {
torchBrightness = 0.01 // 0.0은 에러발생
return
}
setTorch(torchBrightness)
}
}
private func setBrightness(_ displayBrightness: CGFloat) {
UIScreen.main.brightness = displayBrightness
}
private func setTorch(_ torchBrightness: Float) {
guard let device = AVCaptureDevice.default(for: .video), device.hasTorch else {
return
}
do {
try device.lockForConfiguration()
try device.setTorchModeOn(level: torchBrightness)
// 참고: 플래시 끄기
// device.torchMode = .off
device.unlockForConfiguration()
} catch {
print(#function, error.localizedDescription)
}
}
var body: some View {
HStack(spacing: 0) {
VStack(spacing: 0) {
Rectangle()
.fill(DEBUG_MODE ? .cyan : .white)
.onTapGesture {
displayBrightness += 0.1
}
Rectangle()
.onTapGesture {
displayBrightness -= 0.1
}
}
VStack(spacing: 0) {
Rectangle()
.onTapGesture {
torchBrightness += 0.1
}
Rectangle()
.fill(DEBUG_MODE ? .cyan : .white)
.onTapGesture {
torchBrightness -= 0.1
}
}
}
.foregroundColor(.white)
.ignoresSafeArea()
.onChange(of: scenePhase) { scenePhase in
switch scenePhase {
case .background:
break
case .inactive:
setBrightness(outsideDisplayBrightness)
// 플래시(torch)는 저절로 꺼지기 때문에 굳이 코드로 넣지 않음
case .active:
outsideDisplayBrightness = UIScreen.main.brightness
setTorch(torchBrightness)
setBrightness(displayBrightness)
@unknown default:
break
}
}
}
}
아이폰 화면에서 왼쪽 상하 부분을 누르면 화면 밝기가 조절되고, 오른쪽 상하 부분을 누르면 플래시 밝기가 조절됩니다.
This post is licensed under
CC BY 4.0
by the author.
