iOS Basics Skill
Foundation knowledge for iOS application development including project setup, app lifecycle, and configuration.
Prerequisites
- Xcode 15+ installed
- Apple Developer account (for device testing)
- macOS Sonoma or later recommended
Parameters
parameters:
ios_deployment_target:
type: string
default: "15.0"
description: Minimum iOS version supported
device_family:
type: array
items: [iphone, ipad]
default: [iphone, ipad]
interface_style:
type: string
enum: [storyboard, programmatic, swiftui]
default: programmatic
Topics Covered
App Lifecycle
| State |
Description |
Callback |
| Not Running |
App not launched |
- |
| Inactive |
Transitioning |
sceneWillResignActive |
| Active |
Running in foreground |
sceneDidBecomeActive |
| Background |
Running in background |
sceneDidEnterBackground |
| Suspended |
In memory, not executing |
- |
Project Structure
MyApp/
├── MyApp.xcodeproj
├── MyApp/
│ ├── App/
│ │ ├── AppDelegate.swift
│ │ ├── SceneDelegate.swift
│ │ └── Info.plist
│ ├── Features/
│ │ └── Home/
│ │ ├── HomeViewController.swift
│ │ └── HomeViewModel.swift
│ ├── Core/
│ │ ├── Extensions/
│ │ ├── Utilities/
│ │ └── Services/
│ └── Resources/
│ ├── Assets.xcassets
│ └── LaunchScreen.storyboard
└── MyAppTests/
Info.plist Keys
| Key |
Purpose |
Required |
CFBundleDisplayName |
App name shown to user |
Yes |
CFBundleIdentifier |
Unique app identifier |
Yes |
UILaunchStoryboardName |
Launch screen |
Yes |
NSCameraUsageDescription |
Camera permission |
If using camera |
NSPhotoLibraryUsageDescription |
Photo library permission |
If accessing photos |
UIBackgroundModes |
Background capabilities |
If running in background |
Code Examples
SceneDelegate Setup (iOS 13+)
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
private var appCoordinator: AppCoordinator?
func scene(_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
let navigationController = UINavigationController()
appCoordinator = AppCoordinator(navigationController: navigationController)
appCoordinator?.start()
window.rootViewController = navigationController
window.makeKeyAndVisible()
self.window = window
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Save state, release resources
CoreDataStack.shared.saveContext()
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Refresh data if needed
NotificationCenter.default.post(name: .appWillEnterForeground, object: nil)
}
}
Permission Request Pattern
import AVFoundation
import Photos
final class PermissionManager {
static let shared = PermissionManager()
func requestCameraPermission() async -> Bool {
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
return true
case .notDetermined:
return await AVCaptureDevice.requestAccess(for: .video)
case .denied, .restricted:
return false
@unknown default:
return false
}
}
func requestPhotoLibraryPermission() async -> Bool {
let status = PHPhotoLibrary.authorizationStatus(for: .readWrite)
switch status {
case .authorized, .limited:
return true
case .notDetermined:
let newStatus = await PHPhotoLibrary.requestAuthorization(for: .readWrite)
return newStatus == .authorized || newStatus == .limited
case .denied, .restricted:
return false
@unknown default:
return false
}
}
func openSettings() {
guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
UIApplication.shared.open(url)
}
}
Background Task Handling
import BackgroundTasks
final class BackgroundTaskManager {
static let shared = BackgroundTaskManager()
private let refreshTaskId = "com.app.refresh"
private let processingTaskId = "com.app.processing"
func registerTasks() {
BGTaskScheduler.shared.register(forTaskWithIdentifier: refreshTaskId, using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
BGTaskScheduler.shared.register(forTaskWithIdentifier: processingTaskId, using: nil) { task in
self.handleProcessing(task: task as! BGProcessingTask)
}
}
func scheduleRefresh() {
let request = BGAppRefreshTaskRequest(identifier: refreshTaskId)
request.earliestBeginDate = Date(timeIntervalSinceNow: 15 * 60) // 15 min
do {
try BGTaskScheduler.shared.submit(request)
} catch {
Logger.background.error("Failed to schedule refresh: \(error)")
}
}
private func handleAppRefresh(task: BGAppRefreshTask) {
scheduleRefresh() // Reschedule
let refreshTask = Task {
do {
try await DataSyncService.shared.syncAll()
task.setTaskCompleted(success: true)
} catch {
task.setTaskCompleted(success: false)
}
}
task.expirationHandler = {
refreshTask.cancel()
}
}
}
Troubleshooting
Common Issues
| Issue |
Cause |
Solution |
| Black screen on launch |
Missing root VC |
Set window.rootViewController |
| Permission dialog not showing |
Already denied |
Check status, guide to Settings |
| Background task not running |
Not registered |
Call register in didFinishLaunching |
| Launch image wrong size |
Missing assets |
Add all required sizes to LaunchScreen |
Debug Tips
# Simulate background fetch
xcrun simctl spawn booted debug-background refresh com.app.bundleid
# Check app lifecycle in console
# Filter: subsystem:com.apple.UIKit category:Lifecycle
# Reset permissions
xcrun simctl privacy booted reset all com.app.bundleid
Validation Rules
validation:
- rule: info_plist_usage_descriptions
severity: error
check: All permission usage descriptions must be non-empty
- rule: launch_screen_required
severity: error
check: LaunchScreen.storyboard or launch screen in Info.plist
- rule: supported_orientations
severity: warning
check: Define supported orientations for all device types
Integration Patterns
// AppDelegate + SceneDelegate coordination
extension Notification.Name {
static let appWillEnterForeground = Notification.Name("appWillEnterForeground")
static let appDidBecomeActive = Notification.Name("appDidBecomeActive")
static let userDidLogin = Notification.Name("userDidLogin")
}
Usage
Skill("swift-ios-basics")
Related Skills
swift-uikit - UIKit components
swift-swiftui - SwiftUI alternative
swift-testing - Testing iOS apps