/inheritance
SwiftData class inheritance patterns for hierarchical models with type-based querying, polymorphic relationships, and when to choose inheritance vs enums. Use when designing SwiftData model hierarchies.
$ npx -y skills add rshankras/claude-code-apple-skills --skill inheritance --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/inheritance
Context preview
The summary Claude sees to decide when to auto-load this skill.
SwiftData class inheritance patterns for hierarchical models with type-based querying, polymorphic relationships, and when to choose inheritance vs enums. Use when designing SwiftData model hierarchies.
SKILL.md
inheritance.SKILL.mdname: swiftdata-inheritance
description: SwiftData class inheritance patterns for hierarchical models with type-based querying, polymorphic relationships, and when to choose inheritance vs enums. Use when designing SwiftData model hierarchies.
allowed-tools: [Read, Glob, Grep]
last_verified: 2026-07-16
review_by: 2027-06-22
SwiftData Class Inheritance
Guide for implementing class inheritance in SwiftData models. Covers when to use inheritance versus enums or protocols, how to annotate subclasses, query across hierarchies, and avoid common pitfalls with schema migrations and relationship modeling.
When This Skill Activates
- User is designing a SwiftData model hierarchy with shared base properties
- User asks about `@Model` on subclasses or how inheritance works in SwiftData
- User needs to query across a type hierarchy (all trips vs only business trips)
- User is deciding between inheritance, enums, or protocols for model variants
- User has issues with polymorphic relationships or type casting in SwiftData
- User is migrating a Core Data inheritance hierarchy to SwiftData
Decision Tree
Do your model variants share a common identity and most properties?
|
+-- YES: Clear IS-A relationship (BusinessTrip IS-A Trip)
| |
| +-- Subclasses add significant unique properties or behavior?
| | +-- YES --> Use class inheritance (this skill)
| | +-- NO, just 1-2 distinguishing fields --> Use enum property on base model
| |
| +-- Need to query "all trips" AND "only business trips"?
| +-- YES --> Inheritance gives you both for free
| +-- Only one type at a time --> Enum filter is simpler
|
+-- NO: Models share only a few properties
| +-- Use protocol conformance (no SwiftData inheritance needed)
|
+-- UNCERTAIN: Could go either way
+-- Prefer enum on base model (simpler schema, easier migrations)
+-- Promote to inheritance later if variants diverge significantlyWhen to Use Inheritance
- There is a meaningful IS-A relationship (a `BusinessTrip` fundamentally IS a `Trip`)
- Subclasses add substantial unique stored properties
- You need deep queries (fetch all `Trip` instances regardless of subtype) and shallow queries (fetch only `BusinessTrip`)
- Polymorphic relationships are required (a `[Trip]` array holding mixed subtypes)
When to Avoid Inheritance
- Subclasses share only a few properties -- use a protocol instead
- A boolean flag or enum could represent the distinction without separate classes
- You want to minimize schema migration complexity
- The hierarchy would go deeper than two levels
API Patterns
Base Model Declaration
Apply `@Model` to the base class. All persistent properties live here.
@Model
class Trip {
var name: String
var startDate: Date
var endDate: Date
@Attribute(.preserveValueOnDeletion)
var identifier: UUID
@Relationship(deleteRule: .cascade, inverse: \Accommodation.trip)
var accommodations: [Accommodation] = []
init(name: String, startDate: Date, endDate: Date) {
self.identifier = UUID()
self.name = name
self.startDate = startDate
self.endDate = endDate
}
}Subclass Declaration
Apply `@Model` to each subclass. Call `super.init()` and add subclass-specific stored properties.
@Model
class BusinessTrip: Trip {
var company: String
var expenseReport: String?
var meetingAgenda: String?
init(name: String, startDate: Date, endDate: Date, company: String) {
self.company = company
super.init(name: name, startDate: startDate, endDate: endDate)
}
}
@Model
class PersonalTrip: Trip {
enum Reason: String, Codable {
case vacation
case family
case adventure
}
var reason: Reason
var companions: [String] = []
init(name: String, startDate: Date, endDate: Date, reason: Reason) {
self.reason = reason
super.init(name: name, startDate: startDate, endDate: endDate)
}
}Relationships Across the Hierarchy
Relationships defined on the base class apply to all subclasses:
@Model
class Accommodation {
var name: String
// Points to Trip -- could be BusinessTrip or PersonalTrip at runtime
@Relationship(inverse: \Trip.accommodations)
var trip: Trip?
init(name: String) { self.name = name }
}ModelContainer Configuration
Register the base class. SwiftData discovers subclasses automatically.
// Register Trip -- BusinessTrip and PersonalTrip are included automatically
let container = try ModelContainer(for: Trip.self, Accommodation.self, Itinerary.self)
Querying Hierarchies
Deep Query (All Subclasses)
Querying the base class returns instances of every subclass.
// Returns Trip, BusinessTrip, and PersonalTrip instances
@Query(sort: \Trip.startDate)
var allTrips: [Trip]
Type Filtering with Predicate
Narrow results to a specific subclass using `is` or `as?` in a `#Predicate`.
// Only BusinessTrip instances
let businessOnly = #Predicate<Trip> { trip in
trip is BusinessTrip
}
@Query(filter: #Predicate<Trip> { $0 is BusinessTrip }, sort: \Trip.startDate)
var businessTrips: [Trip]Subclass Property Filtering
Access subclass-specific properties with conditional casting inside the predicate.
let vacationTrips = #Predicate<Trip> { trip in
if let personal = trip as? PersonalTrip {
personal.reason == .vacation
} else {
false
}
}Enum-Based Filter Switching in UI
A common pattern for filter controls that switch between all trips and a specific type.
enum TripFilter: String, CaseIterable, Identifiable {
case all, business, personal
var id: String { rawValue }
}
struct TripListView: View {
@State private var filter: TripFilter = .all
@Query(sort: \Trip.startDate) var allTrips: [Trip]
var filteredTrips: [Trip] {
switch filter {
cRead more
name: swiftdata-inheritance description: SwiftData class inheritance patterns for hierarchical models with type-based querying, polymorphic relationships, and when to choose inheritance vs enums. Use when designing SwiftData model hierarchies. allowed-tools: [Read, Glob, Grep] last_verified: 2026-07-16 review_by: 2027-06-22
SwiftData Class Inheritance
Guide for implementing class inheritance in SwiftData models. Covers when to use inheritance versus enums or protocols, how to annotate subclasses, query across hierarchies, and avoid common pitfalls with schema migrations and relationship modeling.
When This Skill Activates
- User is designing a SwiftData model hierarchy with shared base properties
- User asks about `@Model` on subclasses or how inheritance works in SwiftData
- User needs to query across a type hierarchy (all trips vs only business trips)
- User is deciding between inheritance, enums, or protocols for model variants
- User has issues with polymorphic relationships or type casting in SwiftData
- User is migrating a Core Data inheritance hierarchy to SwiftData
Decision Tree
Do your model variants share a common identity and most properties?
|
+-- YES: Clear IS-A relationship (BusinessTrip IS-A Trip)
| |
| +-- Subclasses add significant unique properties or behavior?
| | +-- YES --> Use class inheritance (this skill)
| | +-- NO, just 1-2 distinguishing fields --> Use enum property on base model
| |
| +-- Need to query "all trips" AND "only business trips"?
| +-- YES --> Inheritance gives you both for free
| +-- Only one type at a time --> Enum filter is simpler
|
+-- NO: Models share only a few properties
| +-- Use protocol conformance (no SwiftData inheritance needed)
|
+-- UNCERTAIN: Could go either way
+-- Prefer enum on base model (simpler schema, easier migrations)
+-- Promote to inheritance later if variants diverge significantlyWhen to Use Inheritance
- There is a meaningful IS-A relationship (a `BusinessTrip` fundamentally IS a `Trip`)
- Subclasses add substantial unique stored properties
- You need deep queries (fetch all `Trip` instances regardless of subtype) and shallow queries (fetch only `BusinessTrip`)
- Polymorphic relationships are required (a `[Trip]` array holding mixed subtypes)
When to Avoid Inheritance
- Subclasses share only a few properties -- use a protocol instead
- A boolean flag or enum could represent the distinction without separate classes
- You want to minimize schema migration complexity
- The hierarchy would go deeper than two levels
API Patterns
Base Model Declaration
Apply `@Model` to the base class. All persistent properties live here.
@Model
class Trip {
var name: String
var startDate: Date
var endDate: Date
@Attribute(.preserveValueOnDeletion)
var identifier: UUID
@Relationship(deleteRule: .cascade, inverse: \Accommodation.trip)
var accommodations: [Accommodation] = []
init(name: String, startDate: Date, endDate: Date) {
self.identifier = UUID()
self.name = name
self.startDate = startDate
self.endDate = endDate
}
}Subclass Declaration
Apply `@Model` to each subclass. Call `super.init()` and add subclass-specific stored properties.
@Model
class BusinessTrip: Trip {
var company: String
var expenseReport: String?
var meetingAgenda: String?
init(name: String, startDate: Date, endDate: Date, company: String) {
self.company = company
super.init(name: name, startDate: startDate, endDate: endDate)
}
}
@Model
class PersonalTrip: Trip {
enum Reason: String, Codable {
case vacation
case family
case adventure
}
var reason: Reason
var companions: [String] = []
init(name: String, startDate: Date, endDate: Date, reason: Reason) {
self.reason = reason
super.init(name: name, startDate: startDate, endDate: endDate)
}
}Relationships Across the Hierarchy
Relationships defined on the base class apply to all subclasses:
@Model
class Accommodation {
var name: String
// Points to Trip -- could be BusinessTrip or PersonalTrip at runtime
@Relationship(inverse: \Trip.accommodations)
var trip: Trip?
init(name: String) { self.name = name }
}ModelContainer Configuration
Register the base class. SwiftData discovers subclasses automatically.
// Register Trip -- BusinessTrip and PersonalTrip are included automatically let container = try ModelContainer(for: Trip.self, Accommodation.self, Itinerary.self)
Querying Hierarchies
Deep Query (All Subclasses)
Querying the base class returns instances of every subclass.
// Returns Trip, BusinessTrip, and PersonalTrip instances @Query(sort: \Trip.startDate) var allTrips: [Trip]
Type Filtering with Predicate
Narrow results to a specific subclass using `is` or `as?` in a `#Predicate`.
// Only BusinessTrip instances
let businessOnly = #Predicate<Trip> { trip in
trip is BusinessTrip
}
@Query(filter: #Predicate<Trip> { $0 is BusinessTrip }, sort: \Trip.startDate)
var businessTrips: [Trip]Subclass Property Filtering
Access subclass-specific properties with conditional casting inside the predicate.
let vacationTrips = #Predicate<Trip> { trip in
if let personal = trip as? PersonalTrip {
personal.reason == .vacation
} else {
false
}
}Enum-Based Filter Switching in UI
A common pattern for filter controls that switch between all trips and a specific type.
enum TripFilter: String, CaseIterable, Identifiable {
case all, business, personal
var id: String { rawValue }
}
struct TripListView: View {
@State private var filter: TripFilter = .all
@Query(sort: \Trip.startDate) var allTrips: [Trip]
var filteredTrips: [Trip] {
switch filter {
cA collection of Claude Code skills for iOS, macOS, watchOS, visionOS, and Apple platform development. These skills help you plan and build apps, maintain code quality, ensure HIG compliance, and guide you from idea to App Store.
Repo: rshankras/claude-code-apple-skills
Other skills on rshankras-apple-skills.
- /app-store
App Store optimization and marketing skills for descriptions, screenshots, keywords, review responses, and comprehensive promotional strategy. Use when user needs help with App Store presence, ASO, marketing, or customer communication.
Open skill - /ad-attribution
Privacy-preserving ad measurement with AdAttributionKit (SKAdNetwork's successor) — install and re-engagement attribution, conversion-value strategy under crowd anonymity, and end-to-end postback testing. Use when running paid acquisition beyond Apple Ads, measuring
Open skill - /app-description-writer
Generate compelling App Store descriptions that convert browsers into users. Use when writing initial descriptions, improving existing copy, or drafting promotional text and What's New for a major update.
Open skill - /apple-search-ads
Apple Search Ads campaign strategy for indie developers — paid acquisition, keyword bidding, budget planning, and ROAS optimization. Use when user asks about running ads, paid user acquisition, or Apple Search Ads campaigns.
Open skill - /iap-finalizer
Take a one-time in-app purchase from MISSING_METADATA to READY_TO_SUBMIT in App Store Connect — set its price schedule and localized display name/description (and optional review screenshot) via the ASC REST API. Use at Phase 6 (Pre-Release), after the IAP is built in-app (Phase
Open skill - /keyword-optimizer
Optimize app title, subtitle, and keywords for maximum App Store discoverability. Use when launching a new app, improving search rankings, entering new markets/languages, or safely optimizing ASO for an app with existing traffic.
Open skill

