@@ -3,13 +3,12 @@ import SVGKit
33import UIKit
44
55final class MapMarkerBuilder {
6- private let iconCache = NSCache < NSString , UIImage > ( )
6+ private let iconCache : NSCache < NSNumber , UIImage > = {
7+ let c = NSCache < NSNumber , UIImage > ( )
8+ c. countLimit = 512
9+ return c
10+ } ( )
711 private var tasks : [ String : Task < Void , Never > ] = [ : ]
8- private let queue = DispatchQueue (
9- label: " map.marker.render " ,
10- qos: . userInitiated,
11- attributes: . concurrent
12- )
1312
1413 func build( _ m: RNMarker , icon: UIImage ? ) -> GMSMarker {
1514 let marker = GMSMarker (
@@ -35,7 +34,8 @@ final class MapMarkerBuilder {
3534 }
3635 m. zIndex. map { marker. zIndex = Int32 ( $0) }
3736
38- DispatchQueue . main. asyncAfter ( deadline: . now( ) + 0.25 ) { [ weak marker] in
37+ onMainAsync { [ weak marker] in
38+ try ? await Task . sleep ( nanoseconds: 250_000_000 )
3939 marker? . tracksViewChanges = false
4040 }
4141
@@ -99,7 +99,8 @@ final class MapMarkerBuilder {
9999 )
100100 }
101101
102- DispatchQueue . main. asyncAfter ( deadline: . now( ) + 0.25 ) { [ weak m] in
102+ onMainAsync { [ weak m] in
103+ try ? await Task . sleep ( nanoseconds: 250_000_000 )
103104 m? . tracksViewChanges = false
104105 }
105106 }
@@ -144,7 +145,8 @@ final class MapMarkerBuilder {
144145 guard let self else { return }
145146 defer { self . tasks. removeValue ( forKey: id) }
146147
147- let img = await self . renderUIImage ( m)
148+ let scale = UIScreen . main. scale
149+ let img = await self . renderUIImage ( m, scale)
148150 guard let img, !Task. isCancelled else { return }
149151
150152 self . iconCache. setObject ( img, forKey: key)
@@ -172,65 +174,38 @@ final class MapMarkerBuilder {
172174 iconCache. removeAllObjects ( )
173175 }
174176
175- private func renderUIImage( _ m: RNMarker ) async -> UIImage ? {
176- guard let iconSvg = m. iconSvg else {
177- return nil
178- }
179-
180- return await withTaskCancellationHandler (
181- operation: {
182- await withCheckedContinuation {
183- ( cont: CheckedContinuation < UIImage ? , Never > ) in
184- queue. async {
185- if Task . isCancelled {
186- cont. resume ( returning: nil )
187- return
188- }
189-
190- let targetW = max ( 1 , Int ( CGFloat ( iconSvg. width) ) )
191- let targetH = max ( 1 , Int ( CGFloat ( iconSvg. height) ) )
192- let size = CGSize ( width: targetW, height: targetH)
193-
194- guard
195- let data = iconSvg. svgString. data ( using: . utf8) ,
196- let svgImg = SVGKImage ( data: data)
197- else {
198- cont. resume ( returning: nil )
199- return
200- }
201-
202- svgImg. size = size
203-
204- if Task . isCancelled {
205- cont. resume ( returning: nil )
206- return
207- }
208-
209- guard let base = svgImg. uiImage else {
210- cont. resume ( returning: nil )
211- return
212- }
213-
214- let scale = UIScreen . main. scale
215- let img : UIImage
216- if let cg = base. cgImage {
217- img = UIImage ( cgImage: cg, scale: scale, orientation: . up)
218- } else {
219- let fmt = UIGraphicsImageRendererFormat . default ( )
220- fmt. opaque = false
221- fmt. scale = scale
222- let renderer = UIGraphicsImageRenderer ( size: size, format: fmt)
223- img = renderer. image { _ in
224- base. draw ( in: CGRect ( origin: . zero, size: size) )
225- }
226- }
227-
228- cont. resume ( returning: img)
229- }
230- }
177+ private func renderUIImage( _ m: RNMarker , _ scale: CGFloat ) async -> UIImage ? {
178+ guard let iconSvg = m. iconSvg,
179+ let data = iconSvg. svgString. data ( using: . utf8)
180+ else { return nil }
231181
232- } ,
233- onCancel: { }
182+ let size = CGSize (
183+ width: max ( 1 , CGFloat ( iconSvg. width) ) ,
184+ height: max ( 1 , CGFloat ( iconSvg. height) )
234185 )
186+
187+ return await Task . detached ( priority: . userInitiated) {
188+ autoreleasepool {
189+ guard let svgImg = SVGKImage ( data: data) else { return nil }
190+ svgImg. size = size
191+
192+ guard !Task. isCancelled else { return nil }
193+ guard let base = svgImg. uiImage else { return nil }
194+
195+ if let cg = base. cgImage {
196+ return UIImage ( cgImage: cg, scale: scale, orientation: . up)
197+ }
198+ guard !Task. isCancelled else { return nil }
199+ let fmt = UIGraphicsImageRendererFormat . default ( )
200+ fmt. opaque = false
201+ fmt. scale = scale
202+ guard !Task. isCancelled else { return nil }
203+ let renderer = UIGraphicsImageRenderer ( size: size, format: fmt)
204+ return renderer. image { _ in
205+ base. draw ( in: CGRect ( origin: . zero, size: size) )
206+ }
207+ }
208+ } . value
235209 }
210+
236211}
0 commit comments