uikit-expert — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited uikit-expert (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Use this skill to build, review, or improve UIKit features with correct lifecycle management, performant Auto Layout, modern collection view APIs, and safe navigation patterns. Prioritize native APIs, Apple's documented best practices, and performance-conscious patterns. This skill focuses on facts and best practices without enforcing specific architectural patterns (no MVVM/VIPER/Coordinator mandates).
viewIsAppearing for geometry, viewDidLoad for setup only (see references/view-controller-lifecycle.md)translatesAutoresizingMaskIntoConstraints (see references/auto-layout.md)references/modern-collection-views.md)UIContentConfiguration, not deprecated textLabel (see references/cell-configuration.md)references/list-performance.md)references/navigation-patterns.md)references/animation-patterns.md)[weak self], delegate ownership, Timer/CADisplayLink traps (see references/memory-management.md)references/concurrency-main-thread.md)references/uikit-swiftui-interop.md)references/image-loading.md)references/keyboard-scroll.md)references/adaptive-appearance.md)references/modern-uikit-apis.md)viewDidLoad with viewIsAppearing (see references/view-controller-lifecycle.md)isActive or modify .constant (see references/auto-layout.md)UITableViewDataSource to diffable data sources (see references/modern-collection-views.md)textLabel/detailTextLabel/imageView with UIContentConfiguration (see references/cell-configuration.md)reloadItems with reconfigureItems for in-place cell updates (see references/list-performance.md)navigationItem not navigationBar (see references/navigation-patterns.md)references/animation-patterns.md)[weak self], cancel Tasks in viewDidDisappear, use block-based Timer (see references/memory-management.md)DispatchQueue.main.async with Task (see references/concurrency-main-thread.md)UIImage(data:) or full-resolution loading detected (as optional optimization, see references/image-loading.md)UIKeyboardLayoutGuide (see references/keyboard-scroll.md)traitCollectionDidChange with registerForTraitChanges (see references/adaptive-appearance.md)references/modern-uikit-apis.md)viewDidLoad, geometry in viewIsAppearing (see references/view-controller-lifecycle.md)references/auto-layout.md)references/modern-collection-views.md)UIContentConfiguration and configurationUpdateHandler (see references/cell-configuration.md)references/list-performance.md)references/navigation-patterns.md)references/animation-patterns.md)[weak self] in escaping closures, cancel Tasks in lifecycle methods (see references/memory-management.md)@MainActor correctly, store Task references (see references/concurrency-main-thread.md)references/uikit-swiftui-interop.md)references/image-loading.md)UIKeyboardLayoutGuide for keyboard handling (see references/keyboard-scroll.md)references/adaptive-appearance.md)#available and provide sensible fallbacks (see references/modern-uikit-apis.md)viewDidLoad for one-time setup: subviews, constraints, delegates — NOT geometryviewIsAppearing (back-deployed iOS 13+) for geometry-dependent work, trait-based layout, scroll-to-itemviewDidLayoutSubviews fires multiple times — use only for lightweight layer frame adjustmentsviewWillAppear is limited to transition coordinator animations and balanced notification registrationsuper in every lifecycle overrideaddChild → addSubview → didMove(toParent:) — in that exact orderdeinit logging during developmenttranslatesAutoresizingMaskIntoConstraints = false on programmatic viewsNSLayoutConstraint.activate([]) — never individual .isActive = trueisActive or modify .constant — never remove and recreate.required (1000) at runtime — use 999layoutIfNeeded() inside animation block on superview.flushUpdates option to simplify constraint animationUICollectionViewDiffableDataSource with stable identifiers (UUID/database ID, not full model structs)reconfigureItems for content updates, reloadItems only when cell type changesapplySnapshotUsingReloadData for initial population (bypasses diffing)UICollectionViewCompositionalLayout for any non-trivial layoutUICollectionView.CellRegistration — no string identifiers, no manual castingUIContentConfiguration for cell content and UIBackgroundConfiguration for cell backgroundsconfigurationUpdateHandler for state-driven styling (selection, highlight)UINavigationBarAppearance slots (standard, scrollEdge, compact, compactScrollEdge)navigationItem (per-VC) in viewDidLoad, not on navigationBar in viewWillAppearsetViewControllers(_:animated:) for deep links — not sequential push callstransitionCoordinator before push/popprefersLargeTitles once on the bar; use largeTitleDisplayMode per VCUIView.animate — simple one-shot animations; check finished in completionUIViewPropertyAnimator — gesture-driven, interruptible; respect state machine (inactive → active → stopped)CABasicAnimation — layer-only properties (cornerRadius, shadow, 3D transforms); set model value firstUIView.animate(springDuration:bounce:) aligns with SwiftUIlayoutIfNeeded() on superview[weak self] in all escaping closures[weak self], invalidate in viewWillDisappear[weak self] in closure, remove observer in deinit[weak self] in stored inner closuresweak var delegate: SomeDelegate? with AnyObject constraintdeinit — if never called, a retain cycle existsUIViewController is @MainActor — all subclass methods are implicitly main-actorTask references, cancel in viewDidDisappear — not deinitTask.isCancelled before UI updates after awaitTask.detached does NOT inherit actor isolation — explicit MainActor.run needed for UIDispatchQueue.main.sync from background — use await MainActor.runaddChild → addSubview → didMove), retain as stored propertysizingOptions = .intrinsicContentSize (iOS 16+) for Auto Layout containersupdateUIView, not makeUIView; guard against update loopsbyPreparingThumbnail(of:) or prepareForDisplay() for async decodingprepareForReuse, clear image, verify identity on completionUIKeyboardLayoutGuide (iOS 15+) — pin content bottom to view.keyboardLayoutGuide.topAnchorfollowsUndockedKeyboard = true for floating keyboardsregisterForTraitChanges (iOS 17+) instead of deprecated traitCollectionDidChangeUIFont.preferredFont(forTextStyle:) + adjustsFontForContentSizeCategory = true.label, .systemBackground); re-resolve CGColor on trait changesaccessibilityLabel, accessibilityTraits, accessibilityHint on custom viewsUIAccessibilityCustomAction for complex list item actions| Method | Use For |
|---|---|
viewDidLoad | One-time setup: subviews, constraints, delegates |
viewIsAppearing | Geometry-dependent work, trait-based layout, scroll-to-item |
viewWillAppear | Transition coordinator animations only |
viewDidLayoutSubviews | Lightweight layer frame adjustments (fires multiple times) |
viewDidAppear | Start animations, analytics, post-appearance work |
viewWillDisappear | Cancel tasks, invalidate timers, save state |
viewDidDisappear | Final cleanup, cancel background work |
| API | Best For | Interactive | Off Main Thread |
|---|---|---|---|
UIView.animate | Simple one-shot changes | No | No |
UIViewPropertyAnimator | Gesture-driven, interruptible | Yes | No |
CABasicAnimation | Layer properties, 3D transforms | Limited | Yes (Render Server) |
| Deprecated / Legacy | Modern Replacement | Since |
|---|---|---|
traitCollectionDidChange | registerForTraitChanges(_:handler:) | iOS 17 |
| Keyboard notifications | UIKeyboardLayoutGuide | iOS 15 |
cell.textLabel / detailTextLabel | UIListContentConfiguration | iOS 14 |
register + string dequeue | UICollectionView.CellRegistration | iOS 14 |
reloadItems on snapshot | reconfigureItems | iOS 15 |
barTintColor / isTranslucent | UINavigationBarAppearance (4 slots) | iOS 13 |
UICollectionViewFlowLayout (complex) | UICollectionViewCompositionalLayout | iOS 13 |
Manual layoutIfNeeded() in animations | .flushUpdates option | iOS 26 |
| Legacy app lifecycle | UIScene + SceneDelegate | Mandatory iOS 26 |
ObservableObject + manual invalidation | @Observable + UIObservationTrackingEnabled | iOS 18 |
viewDidLoad contains NO geometry-dependent workviewIsAppearing, not viewWillAppearsuperdeinit is implemented for leak verification during developmenttranslatesAutoresizingMaskIntoConstraints = false on all programmatic viewsNSLayoutConstraint.activate([])isActive toggle or .constant modification.required (1000) at runtimesetNeedsLayout() inside layoutSubviews or viewDidLayoutSubviews (infinite loop)reconfigureItems for content updates, not reloadItemsCellRegistration instead of string-based register/dequeueUIContentConfiguration instead of deprecated cell propertiesBUG_IN_CLIENT crash)UINavigationBarAppearance slots configurednavigationItem in viewDidLoad, not navigationBar in viewWillAppearprefersLargeTitles set once; largeTitleDisplayMode per VCUIViewPropertyAnimator state machine respectedCAAnimation sets model value before adding animationfinished parameter[weak self] in all escaping closures[weak self]; invalidated in viewWillDisappearviewDidDisappearweak var on AnyObject-constrained protocolTask.isCancelled checked after await before UI updatesTask.detached for UI work without explicit MainActor.run@MainActor on UIViewController subclasses (already inherited)DispatchQueue.main.sync from backgroundprepareForReuse, clear image, verify identityNSCache sized by decoded bitmap bytes, not file sizeUIHostingController retained as stored property (not local variable)UIHostingController uses full child VC containment (addChild → addSubview → didMove)updateUIView guards against infinite update loops with equality checksUIKeyboardLayoutGuide (iOS 15+) instead of keyboard notificationsfollowsUndockedKeyboard = true on the layout guideregisterForTraitChanges (iOS 17+) instead of traitCollectionDidChangepreferredFont + adjustsFontForContentSizeCategory = trueaccessibilityLabel and accessibilityTraitsUIAccessibilityCustomAction for complex list item actions#available guards with sensible fallbacks for iOS 26+ featuresUIScene lifecycle adopted (mandatory for iOS 26 SDK)UIObservationTrackingEnabled considered for iOS 18+ targetsreferences/view-controller-lifecycle.md — Lifecycle ordering, viewIsAppearing, child VC containmentreferences/auto-layout.md — Batch activation, constraint churn, priority, animation, debuggingreferences/modern-collection-views.md — Diffable data sources, compositional layout, CellRegistrationreferences/cell-configuration.md — UIContentConfiguration, UIBackgroundConfiguration, configurationUpdateHandlerreferences/list-performance.md — Prefetching, cell reuse, reconfigureItems, scroll performancereferences/navigation-patterns.md — Bar appearance, concurrent transitions, large titles, deep linksreferences/animation-patterns.md — UIView.animate, UIViewPropertyAnimator, CAAnimation, springsreferences/memory-management.md — Retain cycles, [weak self], Timer/CADisplayLink/nested closure trapsreferences/concurrency-main-thread.md — @MainActor, Task lifecycle, Swift 6, GCD migrationreferences/uikit-swiftui-interop.md — UIHostingController, UIViewRepresentable, sizing, state bridgingreferences/image-loading.md — Downsampling, decoded bitmap math, cell reuse race conditionreferences/keyboard-scroll.md — UIKeyboardLayoutGuide, scroll view insets, iPad floating keyboardreferences/adaptive-appearance.md — Trait changes, Dynamic Type, dark mode, VoiceOver, accessibilityreferences/modern-uikit-apis.md — Observation framework, updateProperties(), .flushUpdates, UIScene, Liquid GlassThis skill focuses on facts and best practices, not architectural opinions:
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.