swift-ios-basics

Build iOS applications - project setup, app lifecycle, Info.plist, capabilities

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "swift-ios-basics" with this command: npx skills add pluginagentmarketplace/custom-plugin-swift/pluginagentmarketplace-custom-plugin-swift-swift-ios-basics

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

StateDescriptionCallback
Not RunningApp not launched-
InactiveTransitioningsceneWillResignActive
ActiveRunning in foregroundsceneDidBecomeActive
BackgroundRunning in backgroundsceneDidEnterBackground
SuspendedIn 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

KeyPurposeRequired
CFBundleDisplayNameApp name shown to userYes
CFBundleIdentifierUnique app identifierYes
UILaunchStoryboardNameLaunch screenYes
NSCameraUsageDescriptionCamera permissionIf using camera
NSPhotoLibraryUsageDescriptionPhoto library permissionIf accessing photos
UIBackgroundModesBackground capabilitiesIf 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

IssueCauseSolution
Black screen on launchMissing root VCSet window.rootViewController
Permission dialog not showingAlready deniedCheck status, guide to Settings
Background task not runningNot registeredCall register in didFinishLaunching
Launch image wrong sizeMissing assetsAdd 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

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

swift-uikit

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

swift-macos

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

swift-architecture

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

swift-spm

No summary provided by upstream source.

Repository SourceNeeds Review