用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/pluginagentmarketplace/custom-plugin-swift --skill swift-ios-basics命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
基于 SOC 职业分类
正在显示 SKILL.md
| 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 |
Foundation knowledge for iOS application development including project setup, app lifecycle, and configuration.
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
| 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 | - |
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/
| 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 |
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()
}
( : ) {
.default.post(name: .appWillEnterForeground, object: )
}
}
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
.denied, .restricted:
:
}
}
() {
url (string: .openSettingsURLString) { }
.shared.open(url)
}
}
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: ")
}
}
(: ) {
scheduleRefresh()
refreshTask {
{
.shared.syncAll()
task.setTaskCompleted(success: )
} {
task.setTaskCompleted(success: )
}
}
task.expirationHandler {
refreshTask.cancel()
}
}
}
| 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 |
# 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:
- 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
// AppDelegate + SceneDelegate coordination
extension Notification.Name {
static let appWillEnterForeground = Notification.Name("appWillEnterForeground")
static let appDidBecomeActive = Notification.Name("appDidBecomeActive")
static let userDidLogin = Notification.Name("userDidLogin")
}
Skill("swift-ios-basics")
swift-uikit - UIKit componentsswift-swiftui - SwiftUI alternativeswift-testing - Testing iOS apps