CtrlK
BlogDocsLog inGet started
Tessl Logo

dpearson2699/swift-ios-skills

Agent skills for iOS, iPadOS, Swift, SwiftUI, and modern Apple framework development.

71

Quality

89%

Does it follow best practices?

Impact

No eval scenarios have been run

SecuritybySnyk

Advisory

Suggest reviewing before use

Overview
Quality
Evals
Security
Files

predicate-pitfalls.mdskills/swiftdata/references/

#Predicate Pitfalls

Common runtime crashes and build errors when using #Predicate with SwiftData.

Unsupported Expressions

#Predicate compiles Swift expressions into a query representation. Only a subset of Swift is supported. Unsupported expressions compile but crash at runtime.

PatternCrash?Fix
$0.name.uppercased() == "PARIS"Runtime crashUse localizedStandardContains or caseInsensitiveCompare
$0.name.count > 5Runtime crashStore length in a separate property or filter after fetch
$0.tags.count == 0Runtime crashUse $0.tags.isEmpty (iOS 17.4+) or a stored flag
$0.name.isEmpty on optional StringRuntime crash on some OS versionsUse $0.name == nil || $0.name == ""
Custom computed propertyRuntime crashOnly stored @Attribute properties work in predicates
Date.now captured by valueStale predicateCreate a let now = Date() before the predicate and capture it
Enum raw value comparisonRuntime crash (pre-iOS 18)Store the raw value as a separate property, or target iOS 18+
if/else, switch, forBuild errorNot valid inside #Predicate
Arbitrary method callsRuntime crashOnly supported methods (see below) work

Supported Operations

Comparisons: ==, !=, <, <=, >, >=

Logic: &&, ||, !

String: localizedStandardContains(_:), contains(_:), starts(with:), caseInsensitiveCompare(_:)

Collections: contains(where:), allSatisfy(_:), filter(_:), .isEmpty

Other: optional chaining, nil coalescing (??), ternary (? :), arithmetic (+, -, *, /), type casting (as?, is)

Safe Pattern: Build Predicates Dynamically

func tripPredicate(searchText: String, favoritesOnly: Bool) -> Predicate<Trip> {
    let now = Date()
    return #Predicate<Trip> { trip in
        (searchText.isEmpty || trip.destination.localizedStandardContains(searchText))
        && (!favoritesOnly || trip.isFavorite)
        && trip.startDate > now
    }
}

Capture all external values as let bindings outside the predicate closure. The predicate captures them by value at creation time.

Debugging Predicate Crashes

When a predicate crashes at runtime with SwiftData.PredicateError or NSInvalidArgumentException:

  1. Simplify the predicate to a single clause and add clauses back one at a time
  2. Check each clause uses only supported operations on stored properties
  3. Test on the minimum deployment target — some operations were added in later iOS versions

skills

CHANGELOG.md

README.md

tile.json