Skip to main content
ClaudeWave
Skill732 estrellas del repoactualizado 15d ago

swift-formatstyle

This Claude Code skill provides reference documentation and guidance for Swift's FormatStyle protocol and its concrete implementations for formatting numbers, currencies, percentages, dates, durations, measurements, person names, lists, byte counts, and URLs. Use this skill when building iOS 15+ apps that need locale-aware, type-safe formatting of user-facing values, or when designing reusable custom FormatStyle implementations to replace legacy Formatter subclasses.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/dpearson2699/swift-ios-skills /tmp/swift-formatstyle && cp -r /tmp/swift-formatstyle/skills/swift-formatstyle ~/.claude/skills/swift-formatstyle
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Swift FormatStyle

Format values for human-readable display using the `FormatStyle` protocol
and Foundation's concrete format styles. Replaces legacy `Formatter` subclasses
with a type-safe, composable, cacheable API.

Locale-aware display is an i18n concern even when the app is not adding new languages. For user-facing formatted output, always recommend previewing or testing representative locales such as `en_US`, `de_DE`, `ar_SA`, and `ja_JP`; check separators, numbering systems, calendars, currency and unit conventions, text direction, and layout-sensitive output. Keep this skill focused on `FormatStyle`, `ParseableFormatStyle`, parsing, and reusable formatter API design; route broader localization work such as String Catalogs, bundles, plurals, localized copy, and RTL layout review to `ios-localization`. Do not use "not adding languages" as the reason to skip `ios-localization`; locale-sensitive formatting can be a localization review issue without translation work.

Docs: [FormatStyle](https://sosumi.ai/documentation/foundation/formatstyle)

## Contents

- [Quick Reference](#quick-reference)
- [Numbers](#numbers)
- [Currency](#currency)
- [Percentages](#percentages)
- [Dates](#dates)
- [Durations](#durations)
- [Measurements](#measurements)
- [Person Names](#person-names)
- [Lists](#lists)
- [Byte Counts](#byte-counts)
- [URLs](#urls)
- [SwiftUI Integration](#swiftui-integration)
- [Custom FormatStyle](#custom-formatstyle)
- [Common Mistakes](#common-mistakes)
- [Review Checklist](#review-checklist)

## Quick Reference

| Type | Style Access | Example |
|------|-------------|---------|
| `Int`, `Double` | `.number` | `42.formatted(.number.precision(.fractionLength(2)))` → `"42.00"` |
| Currency | `.currency(code:)` | `29.99.formatted(.currency(code: "USD"))` → `"$29.99"` |
| Percent | `.percent` | `0.85.formatted(.percent)` → `"85%"` |
| `Date` | `.dateTime` | `Date.now.formatted(.dateTime.month().day().year())` |
| Date range | `.interval` | `(date1..<date2).formatted(.interval)` |
| Relative date | `.relative(presentation:unitsStyle:)` | `date.formatted(.relative(presentation: .named))` → `"yesterday"` |
| `Duration` | `.time(pattern:)` | `Duration.seconds(3661).formatted(.time(pattern: .hourMinuteSecond))` → `"1:01:01"` |
| `Duration` | `.units(allowed:width:)` | `Duration.seconds(90).formatted(.units(allowed: [.minutes, .seconds]))` → `"1 min, 30 sec"` |
| `Measurement` | `.measurement(width:)` | `Measurement(value: 72, unit: UnitTemperature.fahrenheit).formatted(.measurement(width: .abbreviated))` |
| `PersonNameComponents` | `.name(style:)` | `name.formatted(.name(style: .short))` → `"Tom"` |
| `[String]` | `.list(type:width:)` | `["A","B","C"].formatted(.list(type: .and))` → `"A, B, and C"` |
| Byte count | `.byteCount(style:)` | `Int64(1_048_576).formatted(.byteCount(style: .memory))` → `"1 MB"` |
| `URL` | `.url` | `url.formatted(.url.scheme(.never).host().path())` |

## Numbers

```swift
// Default locale-aware formatting
let n = 1234567.formatted()  // "1,234,567" (en_US)

// Precision
1234.5.formatted(.number.precision(.fractionLength(0...2)))  // "1,234.5"
1234.5.formatted(.number.precision(.significantDigits(3)))    // "1,230"

// Rounding
1234.formatted(.number.rounded(rule: .down, increment: 100)) // "1,200"

// Grouping
1234567.formatted(.number.grouping(.never))                   // "1234567"

// Notation
1_200_000.formatted(.number.notation(.compactName))           // "1.2M"
42.formatted(.number.notation(.scientific))                    // "4.2E1"

// Sign display
(-42).formatted(.number.sign(strategy: .always()))            // "+42" / "-42"

// Locale override
42.formatted(.number.locale(Locale(identifier: "de_DE")))     // "42"
```

Docs: [IntegerFormatStyle](https://sosumi.ai/documentation/foundation/integerformatstyle),
[FloatingPointFormatStyle](https://sosumi.ai/documentation/foundation/floatingpointformatstyle)

## Currency

```swift
29.99.formatted(.currency(code: "USD"))   // "$29.99"
29.99.formatted(.currency(code: "EUR"))   // "€29.99"
29.99.formatted(.currency(code: "JPY"))   // "¥30"

// Customize precision
let style = FloatingPointFormatStyle<Double>.Currency(code: "USD")
    .precision(.fractionLength(0))
1234.56.formatted(style)  // "$1,235"
```

## Percentages

```swift
0.85.formatted(.percent)                                      // "85%"
0.8567.formatted(.percent.precision(.fractionLength(1)))       // "85.7%"
42.formatted(.percent)                                         // "42%"  (integer)
```

## Dates

```swift
let now = Date.now

// Components
now.formatted(.dateTime.year().month().day())           // "Apr 22, 2026"
now.formatted(.dateTime.hour().minute())                // "4:30 PM"
now.formatted(.dateTime.weekday(.wide).month(.wide).day()) // "Wednesday, April 22"

// Predefined styles
now.formatted(date: .long, time: .shortened)            // "April 22, 2026 at 4:30 PM"
now.formatted(date: .abbreviated, time: .omitted)       // "Apr 22, 2026"

// ISO 8601
now.formatted(.iso8601)                                 // "2026-04-22T16:30:00Z"

// Relative
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: .now)!
yesterday.formatted(.relative(presentation: .named))    // "yesterday"
yesterday.formatted(.relative(presentation: .numeric))  // "1 day ago"

// Interval
(date1..<date2).formatted(.interval.month().day().hour().minute())

// Components (countdown-style)
(date1..<date2).formatted(.components(style: .wide, fields: [.day, .hour]))
// "2 days, 5 hours"
```

Docs: [Date.FormatStyle](https://sosumi.ai/documentation/foundation/date/formatstyle),
[Date.RelativeFormatStyle](https://sosumi.ai/documentation/foundation/date/relativeformatstyle),
[Date.IntervalFormatStyle](https://sosumi.ai/documentation/foundation/date/intervalformatstyle)

### Anchored Relative Dates (iOS 18+)

`Date.AnchoredRelativeFormatStyle` formats relative to a fixed anchor date
rather than the current moment.

Docs: [Date.AnchoredRelativeFormatStyle](h
accessorysetupkitSkill

Discover and configure Bluetooth and Wi-Fi accessories using AccessorySetupKit. Use when presenting a privacy-preserving accessory picker, defining discovery descriptors for BLE or Wi-Fi devices, handling accessory session events, migrating from CoreBluetooth permission-based scanning, or setting up accessories without requiring broad Bluetooth permissions.

activitykitSkill

Implement, review, or improve Live Activities and Dynamic Island experiences in iOS apps using ActivityKit. Use when building real-time updating widgets for the Lock Screen and Dynamic Island — delivery tracking, sports scores, ride-sharing status, workout timers, media playback, or any time-sensitive information that updates in real time. Also use when working with ActivityKit, ActivityAttributes, Activity lifecycle (request/update/end), Dynamic Island layouts (compact/minimal/expanded), push-to-update Live Activities, or Lock Screen live widgets.

adattributionkitSkill

Measure ad effectiveness with privacy-preserving attribution using AdAttributionKit. Use when registering ad impressions, handling attribution postbacks, updating conversion values, implementing re-engagement attribution, configuring publisher or advertiser apps, or replacing SKAdNetwork with AdAttributionKit for ad measurement.

alarmkitSkill

Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, StandBy, and paired Apple Watch system UI. Covers AlarmManager scheduling, AlarmAttributes and AlarmPresentation, AlarmButton stop and snooze actions, authorization, state observation, countdown widget-extension handoff, and Live Activity integration. Use when building wake-up alarms, countdown timers, or alarm-style alerts that need Apple's system alarm experience.

app-clipsSkill

Build iOS App Clips with invocation URLs, App Clip Codes, NFC, QR codes, Safari banners, Maps, Messages, target setup, App Store Connect experiences, size/capability constraints, NSUserActivity routing, SKOverlay promotion, App Group/keychain handoff, ephemeral notifications, location confirmation, and full-app migration. Use when creating App Clips or wiring App Clip invocation, experience configuration, or full-app handoff.

app-intentsSkill

Implement App Intents for Siri, Shortcuts, Spotlight, widgets, Control Center, and Apple Intelligence on iOS. Covers AppIntent actions, AppEntity and EntityQuery models, AppShortcutsProvider phrases, IndexedEntity Spotlight indexing, WidgetConfigurationIntent, SnippetIntent, and assistant schemas. Use when exposing app actions or entities to system surfaces.

app-store-optimizationSkill

Optimize App Store product pages for search visibility and conversion. Use for App Store Optimization (ASO), keyword research, app name/subtitle/keyword-field strategy, conversion-focused descriptions and promotional text, screenshot captions and ordering, Custom Product Pages with assigned search keywords, In-App Events, Product Page Optimization tests, localized metadata, ratings/review strategy, and in-app review prompt timing with RequestReviewAction or AppStore.requestReview. Also use when routing ASO vs App Store review, privacy/ATT, or StoreKit implementation boundaries.

app-store-reviewSkill

Prepare for App Store review and prevent rejections. Covers App Store review guidelines, app rejection reasons, PrivacyInfo.xcprivacy privacy manifest requirements, required API reason codes, in-app purchase IAP and StoreKit rules, App Store Guidelines compliance, ATT App Tracking Transparency, EU DMA Digital Markets Act, HIG compliance checklist, app submission preparation, review preparation, metadata requirements, entitlements, widgets, and Live Activities review rules. Use when preparing for App Store submission, fixing rejection reasons, auditing privacy manifests, implementing ATT consent flow, configuring StoreKit IAP, or checking HIG compliance.