0

I'm using SwiftUI Charts to make a LineMark chart. Everything seems to work, except I'm getting this error in the console for every data point that the chart tries to plot.

"Error: this application, or a library it uses, has passed an invalid numeric value (NaN, or not-a-number) to CoreGraphics API and this value is being ignored. Please fix this problem."

I've setup a backtrace in the scheme but I can't make any sense of it.

Here's my code for the chart:

    private var chart: some View {
        
        Chart(viewModel.weatherArray, id: \.DATETIME) {
            LineMark(
                x: .value("Date", $0.DATETIME),
                y: .value("Temp", $0.TMP)
            )
            .lineStyle(StrokeStyle(lineWidth: lineWidth))
            .foregroundStyle(chartColor.gradient)
//            .interpolationMethod(interpolationMethod.mode)
            .symbol(Circle().strokeBorder(lineWidth: lineWidth))
            .symbolSize(showSymbols ? 60 : 0)
            
        }
        //the chart overlay uses the tap gesture to to define the selected element on the chart
        .chartOverlay { proxy in
            GeometryReader { geo in
                Rectangle().fill(.clear).contentShape(Rectangle())
                    .gesture(
                        SpatialTapGesture()
                            .onEnded { value in
                                let element = findElement(location: value.location, proxy: proxy, geometry: geo)
                                if selectedElement?.DATETIME == element?.DATETIME {
                                    // If tapping the same element, clear the selection.
                                    selectedElement = nil
                                } else {
                                    selectedElement = element
                                }
                            }
                            .exclusively(
                                before: DragGesture()
                                    .onChanged { value in
                                        selectedElement = findElement(location: value.location, proxy: proxy, geometry: geo)
                                    }
                            )
                    )
            }
        }
        .chartBackground { proxy in
            ZStack(alignment: .topLeading) {
                GeometryReader { geo in
                    //if showlolipop is the toggle, i dont need that but its simpler to keep it.
                    if showLollipop,
                       let selectedElement {
                        let dateInterval = Calendar.current.dateInterval(of: .hour, for: selectedElement.DATETIME)!
                        let startPositionX1 = proxy.position(forX: dateInterval.start) ?? 0
                        
                        let lineX = startPositionX1 + geo[proxy.plotAreaFrame].origin.x
                        let lineHeight = geo[proxy.plotAreaFrame].maxY
                        let boxWidth: CGFloat = 100
                        let boxOffset = max(0, min(geo.size.width - boxWidth, lineX - boxWidth / 2))
                        
                        //this is the part that defines how the lolipop looks
                        //lolipop stem
                        Rectangle()
                            .fill(.red)
                            .frame(width: 2, height: lineHeight)
                            .position(x: lineX, y: lineHeight / 2)
                        
                        //lolipop head
                        VStack(alignment: .center) {
                            Text("\(selectedElement.DATETIME, format: .dateTime.year(.twoDigits).month(.twoDigits).day().hour())")
                                .font(.callout)
                                .foregroundStyle(.secondary)
                            Text("\(selectedElement.TMP, format: .number) °C")
                                .font(.title2.bold())
                                .foregroundColor(.primary)
                        }
                        
                        //This is the background of the lolipop head
                        .background {
                            ZStack {
                                RoundedRectangle(cornerRadius: 8)
                                    .fill(.background)
                                RoundedRectangle(cornerRadius: 8)
                                    .fill(.quaternary.opacity(0.7))
                            }
                            .padding(.horizontal, -8)
                            .padding(.vertical, -4)
                        }
                        .offset(x: boxOffset)
                    }
                }
            }
        }
    }
    
    //This function is what makes the lolipop work. It finds the info for the labels
     func findElement(location: CGPoint, proxy: ChartProxy, geometry: GeometryProxy) -> WeatherForecastClass? {
        let data = viewModel.weatherArray
        let relativeXPosition = location.x - geometry[proxy.plotAreaFrame].origin.x
        if let date = proxy.value(atX: relativeXPosition) as Date? {
            // Find the closest date element.
            var minDistance: TimeInterval = .infinity
            var index: Int? = nil
            for weatherDataIndex in data.indices {
                let nthWeatherDataDistance = data[weatherDataIndex].DATETIME.distance(to: date)
                if abs(nthWeatherDataDistance) < minDistance {
                    minDistance = abs(nthWeatherDataDistance)
                    index = weatherDataIndex
                }
            }
            if let index {
                return data[index]
            }
        }
        return nil
    }
}

Here's the Backtrace:

Backtrace:
  <CGPathAddLineToPoint+78>
   <$sSo16CGMutablePathRefa12CoreGraphicsE4move2to9transformySo7CGPointV_So17CGAffineTransformVtFTm+113>
    <_Charts_getAxisMarkWitnessTable+3021427>
     <_Charts_getAxisMarkWitnessTable+3022243>
      <_Charts_getAxisMarkWitnessTable+3022291>
       <__CGPathApplyWithBlock_block_invoke+63>
        <_ZNK2CG4Path5applyEU13block_pointerFv17CGPathElementTypePK7CGPointPbE+246>
         <CGPathApplyWithBlock+114>
          <_Charts_getAxisMarkWitnessTable+3016835>
           <_Charts_getAxisMarkWitnessTable+428626>
            <_Charts_getAxisMarkWitnessTable+464967>
             <__swift_memcpy33_4+28201>
              <_Charts_getAxisMarkWitnessTable+425557>
               <_Charts_getAxisMarkWitnessTable+415811>
                <_Charts_getAxisMarkWitnessTable+462771>
                 <_Charts_getAxisMarkWitnessTable+416756>
                  <_Charts_getAxisMarkWitnessTable+416214>
                   <_Charts_getAxisMarkWitnessTable+413871>
                    <_Charts_getAxisMarkWitnessTable+462275>
                     <_Charts_getAxisMarkWitnessTable+416756>
                      <_Charts_getAxisMarkWitnessTable+412741>
                       <_Charts_getAxisMarkWitnessTable+422521>
                        <_Charts_getAxisMarkWitnessTable+464073>
                         <_Charts_getAxisMarkWitnessTable+417649>
                          <_Charts_getAxisMarkWitnessTable+421314>
                           <_Charts_getAxisMarkWitnessTable+432881>
                            <_Charts_getAxisMarkWitnessTable+434361>
                             <_Charts_getAxisMarkWitnessTable+434361>
                              <_Charts_getAxisMarkWitnessTable+434361>
                               <_Charts_getAxisMarkWitnessTable+444893>
                                <_callVisitTableColumnType2+31236>
                                 <__swift_memcpy108_8+1328>
                                  <__swift_memcpy12_4+43911>
                                   <__swift_memcpy12_4+34396>
                                    <_callVisitTableColumnType2+30317>
                                     <block_destroy_helper.6215+63949>
                                      <_ZN2AG5Graph11UpdateStack6updateEv+537>
                                       <_ZN2AG5Graph16update_attributeENS_4data3ptrINS_4NodeEEEj+443>
                                        <_ZN2AG5Graph9value_refENS_11AttributeIDEPK15AGSwiftMetadataRh+123>
                                         <AGGraphGetValue+287>
                                          <__swift_memcpy38_4+28770>
                                           <get_witness_table 7SwiftUI19WidgetConfigurationRzAA13PreferenceKeyRd__r__lAA15Modif
                                            <get_witness_table 7SwiftUI19WidgetConfigurationRzAA13PreferenceKeyRd__r__lAA15Modi
                                             <__swift_memcpy106_8+51272>
                                              <__swift_memcpy106_8+51342>
                                               <-[UIView(CALayerDelegate) layoutSublayersOfLayer:]+2305>
                                               <_ZN2CA5Layer16layout_if_neededEPNS_11TransactionE+526>
                                               <-[UIView(Hierarchy) layoutBelowIfNeeded]+1447>
                                               <__swift_memcpy64_4+166111>
                                               <block_destroy_helper.23+59728>
                                               <block_destroy_helper.23+59750>
                                               <+[UIView(Animation) performWithoutAnimation:]+84>
                                               <__swift_memcpy64_4+161134>
                                               <block_destroy_helper.23+59728>
                                               <block_destroy_helper.23+59750>
                                               <+[UIView(Animation) performWithoutAnimation:]+84>
                                               <__swift_memcpy64_4+166410>
                                               <objectdestroy.142Tm+41107>
                                               <block_destroy_helper+36990>
                                               <block_destroy_helper+35295>
                                               <get_witness_table 7SwiftUI19WidgetConfigurationRzAA13PreferenceKeyRd__r__lAA15M
                                               <__swift_memcpy89_8+19524>
                                               <dynamic_cast_existential_0_superclass_conditional+6323>
                                               <block_destroy_helper.89+25608>
                                               <_callVisitStyleContextType2+33683>
                                               <block_destroy_helper.130+8663>
                                               <block_destroy_helper.130+8519>
                                               <-[UIViewController _setViewAppearState:isAnimating:]+1061>
                                               <-[UIViewController __viewDidAppear:]+146>
                                               <-[UINavigationController viewDidAppear:]+173>
                                               <-[UIViewController _setViewAppearState:isAnimating:]+1061>
                                               <__52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke_2+189>
                                               <__52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke+185>
                                               <__NSARRAY_IS_CALLING_OUT_TO_A_BLOCK__+7>
                                               <-[__NSSingleObjectArrayI enumerateObjectsWithOptions:usingBlock:]+80>
                                               <-[UIViewController _setViewAppearState:isAnimating:]+2066>
                                               <__52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke_2+189>
                                               <__52-[UIViewController _setViewAppearState:isAnimating:]_block_invoke+185>
                                               <__NSARRAY_IS_CALLING_OUT_TO_A_BLOCK__+7>
                                               <-[__NSSingleObjectArrayI enumerateObjectsWithOptions:usingBlock:]+80>
                                               <-[UIViewController _setViewAppearState:isAnimating:]+2066>
                                               <-[UIViewController __viewDidAppear:]+146>
                                               <-[UINavigationController viewDidAppear:]+173>
                                               <-[UIViewController _setViewAppearState:isAnimating:]+1061>
                                               <-[UIViewController __viewDidAppear:]+146>
                                               <-[UIViewController _endAppearanceTransition:]+232>
                                               <-[UINavigationController navigationTransitionView:didEndTransition:fromView:toV
                                               <__49-[UINavigationController _startCustomTransition:]_block_invoke+620>
                                               <-[_UIViewControllerTransitionContext completeTransition:]+101>
                                               <__53-[_UINavigationParallaxTransition animateTransition:]_block_invoke.163+841>
                                               <__UIVIEW_IS_EXECUTING_ANIMATION_COMPLETION_BLOCK__+15>
                                               <-[UIViewAnimationBlockDelegate _didEndBlockAnimation:finished:context:]+797>
                                               <-[UIViewAnimationState sendDelegateAnimationDidStop:finished:]+190>
                                               <-[UIViewAnimationState animationDidStop:finished:]+263>
                                               <-[UIViewAnimationState animationDidStop:finished:]+648>
                                               <_ZN2CA5Layer23run_animation_callbacksEPv+318>
                                               <_dispatch_client_callout+8>
                                               <_dispatch_main_queue_drain+1463>
                                               <_dispatch_main_queue_callback_4CF+31>
                                               <__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__+9>
                                               <__CFRunLoopRun+2482>
                                               <CFRunLoopRunSpecific+560>
                                               <GSEventRunModal+139>
                                               <-[UIApplication _run]+994>
                                               <UIApplicationMain+123>
                                               <__swift_memcpy93_8+11936>
                                               <__swift_memcpy93_8+11597>
                                               <__swift_memcpy195_8+12255>
                                               <$s27SpotWx_MergeBackendFrontend0ab1_cdE3AppV5$mainyyFZ+30>
                                               <main+9>
                                               1079162bf 
[Unknown process name] CGPathCloseSubpath: no current point.

I think I've narrowed the problem down to the interactivity of the chart. When I simplify the chart down to this the errors go away:

    private var chart: some View {
        Chart(viewModel.weatherArray, id: \.DATETIME) {
             LineMark(
                 x: .value("Date", $0.DATETIME),
                 y: .value("Temp", $0.TMP)
             )
             
             
         }
    }
SkimoBen
  • 19
  • 3

1 Answers1

0

I've managed to deduce the problem was this modifier on the Chart element:

.symbolSize(showSymbols ? 60 : 0)

I'm not sure why this happens, as that modifier worked when I was testing it on a static array of data, although all that data was positive. If someone knows what the root of the problem is I'm pretty curious.

SkimoBen
  • 19
  • 3
  • two possibilities but I couldn't check: 1. your circle symbol uses `strokeBorder` which does a negative inset on the circle by half of the linewidth. if the circle is size 0 that might raise the error .. try stroke or border instead. 2. you use symbolSize(by:) which tries to represent the value by a pixel area. Try `.symbolSize(showSymbol ? CGSize(width: 60, height: 60) : CGSize.zero)` instead – or maybe even better switch to `.opacity(showSymbols ? 1 : 0)` – ChrisR Feb 15 '23 at 22:16