axiom-core-location

12
1
Source

Use for Core Location implementation patterns - authorization strategy, monitoring strategy, accuracy selection, background location

Install

mkdir -p .claude/skills/axiom-core-location && curl -L -o skill.zip "https://mcp.directory/api/skills/download/3226" && unzip -o skill.zip -d .claude/skills/axiom-core-location && rm skill.zip

Installs to .claude/skills/axiom-core-location

About this skill

Core Location Patterns

Discipline skill for Core Location implementation decisions. Prevents common authorization mistakes, battery drain, and background location failures.

When to Use

  • Choosing authorization strategy (When In Use vs Always)
  • Deciding monitoring approach (continuous vs significant-change vs CLMonitor)
  • Implementing geofencing or background location
  • Debugging "location not working" issues
  • Reviewing location code for anti-patterns

Related Skills

  • axiom-core-location-ref — API reference, code examples
  • axiom-core-location-diag — Symptom-based troubleshooting
  • axiom-energy — Location as battery subsystem

Part 1: Anti-Patterns (with Time Costs)

Anti-Pattern 1: Premature Always Authorization

Wrong (30-60% denial rate):

// First launch: "Can we have Always access?"
manager.requestAlwaysAuthorization()

Right (5-10% denial rate):

// Start with When In Use
CLServiceSession(authorization: .whenInUse)

// Later, when user triggers background feature:
CLServiceSession(authorization: .always)

Time cost: 15 min to fix code, but 30-60% of users permanently denied = feature adoption destroyed.

Why: Users deny aggressive requests. Start minimal, upgrade when user understands value.


Anti-Pattern 2: Continuous Updates for Geofencing

Wrong (10x battery drain):

for try await update in CLLocationUpdate.liveUpdates() {
    if isNearTarget(update.location) {
        triggerGeofence()
    }
}

Right (system-managed, low power):

let monitor = await CLMonitor("Geofences")
let condition = CLMonitor.CircularGeographicCondition(
    center: target, radius: 100
)
await monitor.add(condition, identifier: "Target")

for try await event in monitor.events {
    if event.state == .satisfied { triggerGeofence() }
}

Time cost: 5 min to refactor, saves 10x battery.


Anti-Pattern 3: Ignoring Stationary Detection

Wrong (wasted battery):

for try await update in CLLocationUpdate.liveUpdates() {
    processLocation(update.location)
    // Never stops, even when device stationary
}

Right (automatic pause/resume):

for try await update in CLLocationUpdate.liveUpdates() {
    if let location = update.location {
        processLocation(location)
    }
    if update.isStationary, let location = update.location {
        // Device stopped moving - updates pause automatically
        // Will resume when device moves again
        saveLastKnownLocation(location)
    }
}

Time cost: 2 min to add check, saves significant battery.


Anti-Pattern 4: No Graceful Denial Handling

Wrong (broken UX):

for try await update in CLLocationUpdate.liveUpdates() {
    guard let location = update.location else { continue }
    // User denied - silent failure, no feedback
}

Right (graceful degradation):

for try await update in CLLocationUpdate.liveUpdates() {
    if update.authorizationDenied {
        showManualLocationPicker()
        break
    }
    if update.authorizationDeniedGlobally {
        showSystemLocationDisabledMessage()
        break
    }
    if let location = update.location {
        processLocation(location)
    }
}

Time cost: 10 min to add handling, prevents confused users.


Anti-Pattern 5: Wrong Accuracy for Use Case

Wrong (battery drain for weather app):

// Weather app using navigation accuracy
CLLocationUpdate.liveUpdates(.automotiveNavigation)

Right (match accuracy to need):

// Weather: city-level is fine
CLLocationUpdate.liveUpdates(.default)  // or .fitness for runners

// Navigation: needs high accuracy
CLLocationUpdate.liveUpdates(.automotiveNavigation)
Use CaseConfigurationAccuracyBattery
Navigation.automotiveNavigation~5mHighest
Fitness tracking.fitness~10mHigh
Store finder.default~10-100mMedium
Weather.default~100m+Low

Time cost: 1 min to change, significant battery savings.


Anti-Pattern 6: Not Stopping Updates

Wrong (battery drain, location icon persists):

func viewDidLoad() {
    Task {
        for try await update in CLLocationUpdate.liveUpdates() {
            updateMap(update.location)
        }
    }
}
// User navigates away, updates continue forever

Right (cancel when done):

private var locationTask: Task<Void, Error>?

func startTracking() {
    locationTask = Task {
        for try await update in CLLocationUpdate.liveUpdates() {
            if Task.isCancelled { break }
            updateMap(update.location)
        }
    }
}

func stopTracking() {
    locationTask?.cancel()
    locationTask = nil
}

Time cost: 5 min to add cancellation, stops battery drain.


Anti-Pattern 7: Ignoring CLServiceSession (iOS 18+)

Wrong (procedural authorization juggling):

func requestAuth() {
    switch manager.authorizationStatus {
    case .notDetermined:
        manager.requestWhenInUseAuthorization()
    case .authorizedWhenInUse:
        if needsFullAccuracy {
            manager.requestTemporaryFullAccuracyAuthorization(...)
        }
    // Complex state machine...
    }
}

Right (declarative goals):

// Just declare what you need - Core Location handles the rest
let session = CLServiceSession(authorization: .whenInUse)

// For feature needing full accuracy
let navSession = CLServiceSession(
    authorization: .whenInUse,
    fullAccuracyPurposeKey: "Navigation"
)

// Monitor diagnostics if needed
for try await diag in session.diagnostics {
    if diag.authorizationDenied { handleDenial() }
}

Time cost: 30 min to migrate, simpler code, fewer bugs.


Part 2: Decision Trees

Authorization Strategy

Q1: Does your feature REQUIRE background location?
├─ NO → Use .whenInUse
│   └─ Q2: Does any feature need precise location?
│       ├─ ALWAYS → Add fullAccuracyPurposeKey to session
│       └─ SOMETIMES → Layer full-accuracy session when feature active
│
└─ YES → Start with .whenInUse, upgrade to .always when user triggers feature
    └─ Q3: When does user first need background location?
        ├─ IMMEDIATELY (e.g., fitness tracker) → Request .always on first relevant action
        └─ LATER (e.g., geofence reminders) → Add .always session when user creates first geofence

Monitoring Strategy

Q1: What are you monitoring for?
├─ USER POSITION (continuous tracking)
│   └─ Use CLLocationUpdate.liveUpdates()
│       └─ Q2: What activity?
│           ├─ Driving navigation → .automotiveNavigation
│           ├─ Walking/cycling nav → .otherNavigation
│           ├─ Fitness tracking → .fitness
│           ├─ Airplane apps → .airborne
│           └─ General → .default or omit
│
├─ ENTRY/EXIT REGIONS (geofencing)
│   └─ Use CLMonitor with CircularGeographicCondition
│       └─ Note: Maximum 20 conditions per app
│
├─ BEACON PROXIMITY
│   └─ Use CLMonitor with BeaconIdentityCondition
│       └─ Choose granularity: UUID only, UUID+major, UUID+major+minor
│
└─ SIGNIFICANT CHANGES ONLY (lowest power)
    └─ Use startMonitoringSignificantLocationChanges() (legacy)
        └─ Updates ~500m movements, works in background

Accuracy Selection

Q1: What's the minimum accuracy that makes your feature work?
├─ TURN-BY-TURN NAV needs 5-10m → .automotiveNavigation / .otherNavigation
├─ FITNESS TRACKING needs 10-20m → .fitness
├─ STORE FINDER needs 100m → .default
├─ WEATHER/CITY needs 1km+ → .default (reduced accuracy acceptable)
└─ GEOFENCING uses system determination → CLMonitor handles it

Q2: Will user be moving fast?
├─ DRIVING (high speed) → .automotiveNavigation (extra processing for speed)
├─ CYCLING/WALKING → .otherNavigation
└─ STATIONARY/SLOW → .default

Always start with lowest acceptable accuracy. Higher accuracy = higher battery drain.

Part 3: Pressure Scenarios

Scenario 1: "Just Use Always Authorization"

Context: PM says "Users want location reminders. Just request Always access on first launch so it works."

Pressure: Ship fast, seems simpler.

Reality:

  • 30-60% of users will deny Always authorization when asked upfront
  • Users who deny can only re-enable in Settings (most won't)
  • Feature adoption destroyed before users understand value

Response:

"Always authorization has 30-60% denial rates when requested upfront. We should start with When In Use, then request Always upgrade when the user creates their first location reminder. This gives us a 5-10% denial rate because users understand why they need it."

Evidence: Apple's own guidance in WWDC 2024-10212: "CLServiceSessions should be taken proactively... hold one requiring full-accuracy when people engage a feature that would warrant a special ask for it."


Scenario 2: "Location Isn't Working in Background"

Context: QA reports "App stops getting location when backgrounded."

Pressure: Quick fix before release.

Wrong fixes:

  • Add all background modes
  • Use allowsBackgroundLocationUpdates = true without understanding
  • Request Always authorization

Right diagnosis:

  1. Check background mode capability exists
  2. Check CLBackgroundActivitySession is held (not deallocated)
  3. Check session started from foreground
  4. Check authorization level (.whenInUse works with CLBackgroundActivitySession)

Response:

"Background location requires specific setup. Let me check: (1) Background mode capability, (2) CLBackgroundActivitySession held during tracking, (3) session started from foreground. Missing any of these causes silent failure."

Checklist:

// 1. Signing & Capabilities → Background Modes → Location updates
// 2. Hold session reference (property, not local variable)
var backgroundSession: CLBackgroundActivitySession?

func startBackgroundTracking() {
    // 3. Must start from foreg

---

*Content truncated.*

axiom-swiftui-nav-diag

CharlesWiltgen

Use when debugging navigation not responding, unexpected pops, deep links showing wrong screen, state lost on tab switch or background, crashes in navigationDestination, or any SwiftUI navigation failure - systematic diagnostics with production crisis defense

54

axiom-swiftui-26-ref

CharlesWiltgen

Use when implementing iOS 26 SwiftUI features - covers Liquid Glass design system, performance improvements, @Animatable macro, 3D spatial layout, scene bridging, WebView/WebPage, AttributedString rich text editing, drag and drop enhancements, and visionOS integration for iOS 26+

33

axiom-extensions-widgets-ref

CharlesWiltgen

Use when implementing widgets, Live Activities, Control Center controls, or app extensions - comprehensive API reference for WidgetKit, ActivityKit, App Groups, and extension lifecycle for iOS 14+

13

axiom-ios-build

CharlesWiltgen

Use when ANY iOS build fails, test crashes, Xcode misbehaves, or environment issue occurs before debugging code. Covers build failures, compilation errors, dependency conflicts, simulator problems, environment-first diagnostics.

253

axiom-camera-capture-ref

CharlesWiltgen

Reference — AVCaptureSession, AVCapturePhotoSettings, AVCapturePhotoOutput, RotationCoordinator, photoQualityPrioritization, deferred processing, AVCaptureMovieFileOutput, session presets, capture device APIs

42

axiom-swiftdata

CharlesWiltgen

Use when working with SwiftData - @Model definitions, @Query in SwiftUI, @Relationship macros, ModelContext patterns, CloudKit integration, iOS 26+ features, and Swift 6 concurrency with @MainActor — Apple's native persistence framework

12

You might also like

flutter-development

aj-geddes

Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.

1,6851,430

ui-ux-pro-max

nextlevelbuilder

"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."

1,2691,335

drawio-diagrams-enhanced

jgtolentino

Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.

1,5441,153

godot

bfollington

This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.

1,359809

nano-banana-pro

garg-aayush

Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.

1,264728

pdf-to-markdown

aliceisjustplaying

Convert entire PDF documents to clean, structured Markdown for full context loading. Use this skill when the user wants to extract ALL text from a PDF into context (not grep/search), when discussing or analyzing PDF content in full, when the user mentions "load the whole PDF", "bring the PDF into context", "read the entire PDF", or when partial extraction/grepping would miss important context. This is the preferred method for PDF text extraction over page-by-page or grep approaches.

1,492684