Skip to content

Let ImageIcon and GroundImageState take an image URL - #24

Merged
wf9a5m75 merged 2 commits into
developfrom
feat/image-icon-url
Nov 6, 2026
Merged

wf9a5m75 merged 2 commits into
developfrom
feat/image-icon-url

Conversation

@wf9a5m75

@wf9a5m75 wf9a5m75 commented Nov 6, 2026

Copy link
Copy Markdown
Contributor

ImageIcon(imageUrl:…) and GroundImageState(bounds:imageUrl:…) load their image from a URL. Same design as js-sdk-core and android-sdk-core.

Behaviour

  • New internal RemoteImageLoader: one URLSession fetch per URL (file URLs too), NSCache of 256, failures remembered and logged once, one-shot callbacks on the main thread. Tests can inject the fetch.
  • ImageIcon: transparent at its final size and anchor until the image arrives; bitmaps rebuilt once per load state under a lock (tile threads read them). hashCode() = URL + parameters + load state, so it changes exactly once. copy() keeps the URL unless image: is passed.
  • MarkerState: a marker given a loading icon registers one callback; on arrival it re-sets the same icon so it redraws through the normal path. Nothing happens if the icon was replaced meanwhile.
  • GroundImageState: @Published imageUrl: URL?. A 1×1 transparent placeholder until loaded, then image is assigned. Changing imageUrl keeps the current image until the new one arrives; stale results are dropped. Assigning image yourself clears imageUrl. Default id is derived from the URL.
  • SwiftUI: GroundImage(bounds:imageUrl:…) overload in MapLayerItems.

API

ImageIcon.init(image:) became a convenience init so both inits share one designated init (signature unchanged, class is final); the rest is additions. Baseline dumped with Xcode 27.2; the second commit records 27.2 in api/TOOLCHAIN (re-dumping with 27.2 changes no other line). Note: test.yml pins Xcode from TOOLCHAIN, so runs on PRs to main need Xcode_27.2.app on the runner.

Verification

  • xcodebuild test: 327 pass (8 new in ImageUrlLoadingTests).
  • iPad (iPad8,4): URL icon appears after loading on MapLibre, MapKit, Google Maps and Mapbox; URL ground image on MapLibre and Google Maps.

ImageIcon(imageUrl:) and GroundImageState(bounds:imageUrl:) load the image
themselves through one shared loader: each URL is fetched once, finished
images are cached, failures are remembered and logged once per URL.

An icon is a transparent image of the same size and anchor until its image
arrives. Its hashCode mixes in the load state (pending / ready / failed),
so it changes exactly once; MarkerState then re-assigns the same icon, which
redraws through the usual icon-change path (StateMutationSignal and $icon).
A marker whose icon was replaced in the meantime is left alone.

A ground image shows a 1x1 transparent image until loaded, then the image is
assigned to `image`. Changing imageUrl keeps the current image until the new
one arrives and drops stale results; assigning `image` clears imageUrl. The
generated id comes from the URL so it is stable across the load.

API: additions only in behaviour. ImageIcon.init(image:) becomes a
convenience initializer of the final class (same signature) so both inits
share one designated initializer.
The ImageIcon / GroundImageState URL baseline was dumped with Xcode 27.2
(27B52). Re-dumping the whole baseline with 27.2 changes no other line,
so this commit only updates the record.
@wf9a5m75
wf9a5m75 merged commit b03d6b9 into develop Nov 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant