home / skills / pluginagentmarketplace / custom-plugin-swift / swift-ios-basics
npx playbooks add skill pluginagentmarketplace/custom-plugin-swift --skill swift-ios-basicsReview the files below or copy the command above to add this skill to your agents.
---
name: swift-ios-basics
description: Build iOS applications - project setup, app lifecycle, Info.plist, capabilities
version: "2.0.0"
sasmp_version: "1.3.0"
bonded_agent: 02-swift-ios
bond_type: PRIMARY_BOND
---
# 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
```yaml
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+)
```swift
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
```swift
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
```swift
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
```bash
# 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
```yaml
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
```swift
// 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