Skip to content

Flyweight ​

Flyweight shares immutable data among many small objects. Each object retains only its unique state while a shared value stores common appearance or behavior.

iOS problem and when to use it ​

A map can show thousands of store annotations. Duplicating the same icon name, tint, and category label in every marker wastes memory and makes style updates harder.

Original example: shared marker styles ​

swift
import Foundation

final class MarkerStyle {
    let symbolName: String
    let tintName: String

    init(symbolName: String, tintName: String) {
        self.symbolName = symbolName
        self.tintName = tintName
    }
}

final class MarkerStyleCatalog {
    private var styles: [String: MarkerStyle] = [:]

    func style(for category: String) -> MarkerStyle {
        if let existing = styles[category] { return existing }
        let created = MarkerStyle(
            symbolName: category == "Cafe" ? "cup.and.saucer" : "mappin",
            tintName: category == "Cafe" ? "brown" : "blue"
        )
        styles[category] = created
        return created
    }
}

struct StoreMarker {
    let latitude: Double
    let longitude: Double
    let storeID: String
    let category: String
}

let catalog = MarkerStyleCatalog()
let marker = StoreMarker(latitude: 37.33, longitude: -122.03,
                         storeID: "store-1", category: "Cafe")
let style = catalog.style(for: marker.category)

Coordinates and store IDs stay per marker; every marker in a category can reference the same immutable MarkerStyle instance. In a MapKit annotation view, translate symbolName and tintName into an image and color at rendering time.

Production decisions ​

Only share immutable style data. Cache rendered UIImage values separately if profiling shows image creation is expensive. The catalog above is a reference type with mutable storage; isolate it to one actor or protect it if multiple tasks access it. Measure memory before adding a flyweight layer, since Swift value types can already be compact.

Separate shared and unique state ​

StoreMarker contains location and store identity because those differ for each annotation. MarkerStyleCatalog maps a category to one immutable MarkerStyle object. The first lookup creates the style; later lookups return that same reference. That is the flyweight: many markers can share one style instead of each retaining a duplicate style object. The catalog key is part of correctness, so the same category must always mean the same style configuration during its lifetime.

From example to MapKit ​

When configuring a reused annotation view, look up the marker's style and set its symbol and tint. MapKit may reuse views, so always apply the entire style, including default values, rather than assuming previous state was cleared. If a theme changes from light to dark, either make styles theme-specific in the cache key or invalidate the catalog. Sharing style metadata is separate from caching rendered images, which may have its own memory cost.

Failure modes and verification ​

Test reference identity for repeated category lookups, distinct styles for different categories, and invalidation after theme changes. Do not share mutable style objects: changing one marker would then change every marker unexpectedly. For small marker counts, plain Swift structs may be efficient enough; profile memory before adding a catalog.

All patterns

Released under the MIT License.