I've asked Alex (my Sidebar pal) - here's his non-judgemental response. I look forward to more judgemental responses from YOU.
In Swift you have three idiomatic ways to give “array–level” capabilities to a group of `PricePoint`s without breaking the type system or introducing unnecessary classes. Pick the one that matches how much behaviour you need and whether the collection ever has to travel over the SwiftData boundary.
────────────────────────────────────────
1. Light-weight: an `Array` extension
────────────────────────────────────────
Best when the extra behaviour is purely convenience, stateless and does **not** need to be stored in SwiftData.
Pros
• Zero extra types
• Works anywhere an `[PricePoint]` exists
Cons
• Harder to discover in code completion
• Extensions are global; avoid polluting the namespace with too many specialised helpers
────────────────────────────────────────
2. Moderate-weight: a wrapper value type
────────────────────────────────────────
Create a small struct whose sole stored property is `[PricePoint]`. Give it richer behaviour, conformance, and even persistence if needed.
Pros
• Methods are discoverable under one semantic type
• You can add `@Model` later if you decide to persist it with SwiftData
Cons
• Requires an extra wrapper (call-sites need `.points` or helpers to bridge)
────────────────────────────────────────
3. Heavy-weight: make the collection itself a SwiftData model
────────────────────────────────────────
If the collection must live in SwiftData you can turn the wrapper above into a `@Model` (or embed the array directly in an existing `@Model` such as `Stock`). But remember SwiftData only supports arrays of value types that are themselves `Codable` & hashable.
────────────────────────────────────────
Recommended approach for your project
────────────────────────────────────────
• If you only need quick calculations inside view-models or chart helpers, **Option 1 (Array extension)** keeps things simple.
• If you foresee unit-testing, richer behaviour, or eventually persisting a slice of candle data, **Option 2 (wrapper struct)** gives you room to grow without polluting the global `Array` symbol space.
• Use **Option 3** only when you truly need SwiftData persistence for the whole collection in one record (e.g. offline caching of a chart).
Tip: Even with Option 2 you can still keep the tiny convenience extension from Option 1 and forward to it, so you don’t duplicate logic.
You won’t break OOP—Swift’s extensions and wrapper types are the idiomatic way to add behaviour to plain value collections.
I think most of my OOP knowledge goes back a few decades before the concept of Array-Extensions entered the playing field.
And I would say this method is great... I just wish there was a better way to unpollute the space of ALL Arrays.
Like what might happen if I mash up a Type Alias with an Array Extension... can that even be done?
What I'd really like...
An answer that told me how to start with Array-Extension and when I need to get a bit more "in-the-weeds" show me the methods to move from the Extension to the Class. And of course when to move into SwiftData.