Accept asset catalog entries in localResources#465
Open
Accept asset catalog entries in localResources#465
Conversation
Generalises SuperwallOptions.localResources from `[String: URL]` to `[String: AssetResource]`. URL conforms to AssetResource so existing call sites are unaffected. New `CatalogAsset(name:bundle:)` registers a Data Set entry from an .xcassets, resolved at load time via NSDataAsset — the iOS equivalent of Android's R.raw.* resource IDs. ObjC keeps a URL-only shim under the same `localResources` name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`UTType.preferredMIMEType` is iOS 14+. On iOS 13, fall back to `UTTypeCopyPreferredTagWithClass` from MobileCoreServices so catalog assets are served with a real MIME type (an `<img>` or `<video>` is refused by WKWebView when the MIME is `application/octet-stream`). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- SWLocalResourcesViewController: when a catalog asset exists but isn't image-decodable, show its UTI and byte count instead of a blank cell. - AssetResource: remove the unused UIKit import. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Satisfies the `trailing_closure` SwiftLint rule — the only remaining project-level lint violation. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
- LocalFileSchemeHandler: remove unreferenced UIKit import. - SuperwallOptions: ObjC setter now replaces only the URL subset of localResources, so CatalogAsset entries registered from Swift survive a subsequent ObjC assignment in mixed Swift/ObjC codebases. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
localResources is documented as set once before configure(), so the "mixed Swift/ObjC post-configure mutation" scenario the merge was guarding against isn't part of the intended usage pattern. The setter goes back to replacing the full dict. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
NSDataAsset only resolves Data Sets, so a typical Image Set logo would fail with "File not found". Try NSDataAsset first (lossless, any file type), then fall back to UIImage(named:in:compatibleWith:)?.pngData() so existing Image Sets work without restructuring the asset catalog. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Calling NSDataAsset on an Image Set triggers a CoreUI log about a wrong-typed lookup. Flip the order so UIImage(named:) runs first — Image Sets resolve cleanly, and NSDataAsset is only reached when there's no Image Set to mistype. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lets customers register an in-memory image directly: "logo": UIImage(named: "Logo")! Served to the webview as image/png via pngData(). Complements CatalogAsset for cases where eager decoding is acceptable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
Comment on lines
265
to
+279
| } | ||
|
|
||
| private func configureCatalogAsset(id: String, catalog: CatalogAsset) { | ||
| idLabel.text = "\(id) (asset: \(catalog.name))" | ||
| spinner.startAnimating() | ||
| DispatchQueue.global(qos: .userInitiated).async { [weak self] in | ||
| let asset = NSDataAsset(name: catalog.name, bundle: catalog.bundle) | ||
| let image = asset.flatMap { UIImage(data: $0.data) } | ||
| DispatchQueue.main.async { | ||
| self?.spinner.stopAnimating() | ||
| if let image = image { | ||
| self?.imageView.image = image | ||
| } else if let asset = asset { | ||
| let byteCount = ByteCountFormatter.string(fromByteCount: Int64(asset.data.count), countStyle: .file) | ||
| self?.showErrorText("No preview\n\(asset.typeIdentifier) · \(byteCount)") |
There was a problem hiding this comment.
Image-Set
CatalogAsset shows "Asset not found" in debug view
configureCatalogAsset loads asset data exclusively via NSDataAsset, but NSDataAsset only resolves Data Set entries — it returns nil for Image Sets. The scheme handler in LocalFileSchemeHandler.load(resource:key:) tries UIImage(named:in:compatibleWith:) first, so an Image Set CatalogAsset is served successfully in the webview, but the debug preview shows "Asset not found" because NSDataAsset finds nothing. The fix is to mirror the scheme handler's resolution order: try UIImage(named:) first, and only then fall back to NSDataAsset.
Prompt To Fix With AI
This is a comment left during a code review.
Path: Sources/SuperwallKit/Debug/SWLocalResourcesViewController.swift
Line: 265-279
Comment:
**Image-Set `CatalogAsset` shows "Asset not found" in debug view**
`configureCatalogAsset` loads asset data exclusively via `NSDataAsset`, but `NSDataAsset` only resolves *Data Set* entries — it returns `nil` for *Image Sets*. The scheme handler in `LocalFileSchemeHandler.load(resource:key:)` tries `UIImage(named:in:compatibleWith:)` first, so an Image Set CatalogAsset is served successfully in the webview, but the debug preview shows "Asset not found" because `NSDataAsset` finds nothing. The fix is to mirror the scheme handler's resolution order: try `UIImage(named:)` first, and only then fall back to `NSDataAsset`.
How can I resolve this? If you propose a fix, please make it concise.Debug view was loading catalog assets via NSDataAsset only, so an Image Set CatalogAsset previewed as "Asset not found" even though the scheme handler resolved it successfully. Try UIImage(named:) first, fall through to NSDataAsset for Data Sets. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes in this pull request
Generalises
SuperwallOptions.localResourcesfrom[String: URL]to[String: AssetResource]so customers can register paywall assets that live inside an asset catalog (.xcassets), achieving parity with the Android SDK'sPaywallResource.FromResources(R.drawable.*).Customer ask (Pylon): customers whose assets live in
.xcassetshad no clean way to register them because asset catalog entries don't expose a file URL.API
New
AssetResourceprotocol is the dictionary's value type. Three conforming types:URL— existing behavior, a file on disk. Conforms out of the box, so existing call sites that assign URL dictionaries compile and behave unchanged.UIImage— register an in-memory image directly; served to the webview asimage/pngviapngData().CatalogAsset(name:bundle:)— deferred lookup into an.xcassets. TriesUIImage(named:in:compatibleWith:)first (Image Set, re-encoded as PNG), then falls back toNSDataAsset(name:bundle:)(Data Set, raw bytes + UTI-derived MIME type). Handles both image assets and non-image Data Sets (video, Lottie JSON, etc.).Implementation notes
LocalFileSchemeHandlerswitches on the resource type.UIImageandCatalogAsset's Image Set path resolve throughUIImage.pngData();CatalogAsset's Data Set path usesNSDataAssetwith a UTI → MIME type conversion.UTType.preferredMIMETypeon iOS 14+ and falls back toUTTypeCopyPreferredTagWithClassfromMobileCoreServiceson iOS 13, so Data Sets get a real MIME type across the supported deployment range.localResourcesname (@objc(localResources)). Asset catalog andUIImageentries are Swift-only.SWLocalResourcesViewController(debug view) previews URL,UIImage, and catalog entries. Non-image catalog assets (e.g. video, JSON) show their UTI and byte count instead of a blank cell.CatalogAssettriesUIImage(named:)beforeNSDataAssetso lookups against Image Sets don't trigger a CoreUI "wrong type" log warning.trailing_closurelint violation inConfigLogic.swift:310while in the area.Tests
Extends
LocalFileSchemeHandlerTests:URLregistered through the unified dictionary still loads bytes and a MIME type.UIImageregistered directly is served asimage/pngwith bytes matchingpngData().CatalogAssetwhose name is missing from the bundle throwsfileNotFound.CatalogAsset's Data Set success path isn't covered because adding a real.xcassetsto the test bundle is non-trivial; the code is small (NSDataAsset.data+ UTI MIME lookup) and will be exercised end-to-end via the demo app.Checklist
LocalFileSchemeHandlerTests).CHANGELOG.mdfor any breaking changes, enhancements, or bug fixes.swiftlintin the main directory and fixed any issues.🤖 Generated with Claude Code