The simple answer is three. The true answer is around two hundred, spread across several files. The popular demo in Swift tutorials shows a snippet like this. You grab the default AVCaptureDevice for the rear camera, call lockForConfiguration, then setTorchModeOn with the intensity. In three lines, the rear LED of the iPhone turns on. In three lines, any junior iOS dev can turn the flashlight on. But three lines do not make a flashlight app. They make a hello world flashlight. A flashlight app worth anything has the rest.
The first thing three lines do not do is handle the permission. AVCaptureDevice is part of Apple’s AVFoundation framework, the same framework used to capture photo, video and audio. To access the camera LED, iOS requires camera permission, even if the app has no intention of capturing any image. That is an Apple restriction, not a product decision. The system is all or nothing. Either the app asks for camera permission and turns on the flashlight, or it does not ask and does not turn on. There is no middle ground. That is why Lanterna BLA has an NSCameraUsageDescription string in Info.plist that says, literally: the camera is used only to control the flashlight on the phone, no image is captured. The app is being honest about what it does under the hood.
The second thing three lines do not do is keep the screen on while the light is on. The iPhone has an idle timer that turns the screen off after thirty seconds without touch, by default. If the user turns on the flashlight to read a medicine label on the bedside table, and the screen goes off in thirty seconds, the screen light goes with it (in the case of the Screen Light mode). To avoid this, the app needs to set the idle timer to disabled while the light is on, and back to enabled when the light goes off. Without this, the app is unusable for sessions longer than half a minute.
The third thing three lines do not do is the Morse SOS. Turning the LED on is one call. Blinking the LED in SOS rhythm, with correct timing, is a loop with five different states (dot, intra letter gap, dash, inter letter gap, repeat gap), each with a specific duration in milliseconds, running in an async Task with weak self to avoid memory leaks, and cancelable when the user taps a different preset or when the timer expires. That is about forty lines just for this logic, plus the cancel method, plus handling when the app goes to background in the middle of the SOS.
The fourth thing three lines do not do is talk to the widget. Lanterna BLA has widgets for the Lock Screen and Home Screen. When the user taps the widget, the app opens directly at the last preset used. For this, app and widget have to share a UserDefaults area via an App Group, with identifier group.bla.vc.Lanterna BLA. On each preset switch, the app saves the current preset in that area. On each launch via deep link from the widget (URL scheme lanternabla, with path last), the app reads that value and opens directly at the saved preset. Simple infrastructure but it has to be done.
The fifth thing three lines do not do is the Privacy Manifest. Since 2024, Apple requires every app to declare which iOS APIs it uses to access user data, even the most innocuous data, in a file called PrivacyInfo.xcprivacy. Lanterna BLA declares only one. Access to UserDefaults for the app’s own purposes, not for tracking. This manifest, together with the NSCameraUsageDescription, is what allows the app to pass Apple’s review without being questioned. Paying attention to these details prevents Apple rejection and two wasted weeks of submission.
The sixth thing three lines do not do is translate. Lanterna BLA has strings translated to ten languages (Brazilian Portuguese, English, Spanish, French, German, Italian, Japanese, Simplified Chinese, Traditional Chinese, Korean). Each string went through editorial review to preserve the studio voice in each language. The localization file has around six hundred and fifty entries, sixty five strings times ten languages. It is not Google translation. It is translation with criterion, in partnership between human and model, with review by someone who understands the brand.
All of that for a flashlight app. Three lines turn the LED on. The other two hundred do the rest. Permission, idle timer, Morse SOS with international timing, widget propagation, Privacy Manifest, translation to ten languages, settings with fixed night theme, Lock Screen widget, deep link, App Group. Each of these pieces is what separates a Swift exercise from a product. And Lanterna BLA is the simplest product BLA has ever built. The next ones will have even more detail, in even fewer obvious lines. Each line in silence. Each decision in editorial.