Precondition failure with several MapViews

I'm trying to use several MapViews in my swiftui list (Xcode 11.2.1). It seems to be Ok to have 4 MapViews but 5 is too much. I get "precondition failure: invalid value type for attribute: 102" with 5 MapViews. Any ideas? Simplified code below.


import SwiftUI

import MapKit


struct ContentView: View {

var body: some View {

List {

MapView().frame(height: 300)

MapView().frame(height: 300)

MapView().frame(height: 300)

MapView().frame(height: 300)

MapView().frame(height: 300) //This is too much...

}

}

}

struct MapView: UIViewRepresentable {

func makeUIView(context: Context) -> MKMapView {

MKMapView()

}

func updateUIView(_ view: MKMapView, context: Context) {

}

}

Answered by keijo in 396677022

Here's how to avoid it. Add VStack inside the List.


List {

VStack {

.....//MapViews here

}

}


Why? No idea... but that seems to help.

Forgot to say that the precondition failure happens when I scroll the list (perhaps an update issue?). I also noticed that the frame height setting has something to do with this. With ".frame(height: 100)" I can show 8 MapViews and get precondition failure with 9.

Can you attach a stack trace here? It would be interesting to know what component is raising the error, and that may help nail down a culprit.

It doesn't really show the stack properly (in source line level). This is the message "2019-12-02 20:41:30.752264+0200 MapKitTest[20750:6545087] precondition failure: invalid value type for attribute: 102". The thread 1 stops in "class AppDelegate: UIResponder, UIApplicationDelegate {" line in AppDelegate.swift. Before that the stack just shows some assembly "

libdyld.dylib`start:

0x7fff51a1dc24 <+0>: nop

-> 0x7fff51a1dc25 <+1>: movl %eax, %edi

0x7fff51a1dc27 <+3>: callq 0x7fff51a479c8 ; symbol stub for: exit

0x7fff51a1dc2c <+8>: hlt

0x7fff51a1dc2d <+9>: nop

"

...but perhaps there's a better way to analyze the stack? Let me know. Thanks!

(I'm using iPhone simulators and real devices...same behaviour)

Xcode also shows this stack frame. This is just a simple test app (source shown above). I assume it is easy to reproduce.


If that may help, I tested (XCode 11.2ß2, MacOS 10.14.6) in playground.


I even added a 6th Mapview, no crash.

import SwiftUI
import MapKit
struct MapView: UIViewRepresentable {
     func makeUIView(context: Context) -> MKMapView {
         MKMapView()
     }
     func updateUIView(_ view: MKMapView, context: Context) {
     }
}

struct ContentView: View {
    var body: some View {
        List {
            MapView().frame(height: 100)
            MapView().frame(height: 100)
            MapView().frame(height: 100)
            MapView().frame(height: 100)
            MapView().frame(height: 100) //This is not too much...
            MapView().frame(height: 100) //This is not too much...
}
    }
}

PlaygroundPage.current.liveView = UIHostingController(rootView: ContentView())


I reduced to 100 height to see preview (preview height is about 700).


But at 300, 3rd shows just a bit,no crash, unless I start scrolling up the view it crashes (preview turns black) on reaching the 4th Map


At 200 size, 4th shows just a bit to start, it crashes scrolling up to show 5th

At 180 size, only first 4 (partially) show to start; it crashes scrolling up to show 5th

At 160 size, only first 4 show to start; it crashes scrolling up to show 5th


At 150, 5th shows a bit to start, I can scroll down to the 6th. No crash



So the pattern seem to be a crash when we load a new mapView that was not partially visible (hence not yet loaded).

Thanks Claude! So you were able to reproduce it. Excellent! I also noticed that I can create tens of MapViews if I remove the frame size definition...but the map is not very useful then. So I'm not sure what to try next.

Accepted Answer

Here's how to avoid it. Add VStack inside the List.


List {

VStack {

.....//MapViews here

}

}


Why? No idea... but that seems to help.

for anyone else who experienced my particular issue. I noticed this with the following scenario.

long story short .tag(step.id) (where step is a core data object) was creating issues on creation and deletions. to this day. no idea why

Code Block
ScrollViewReader { reader in
      VStack(spacing: 0) {
       HStack { Spacer() }
       ForEach( (cycle.steps!.array as! [Step]), id: \.self) { step in
        let index = cycle.steps!.index(of: step)
         
        StepRowLines(
         step: .constant(step),
         index: index + 1,
         stepCase: StepRowLines.ofStepCase(index: index, size: cycle.steps?.count ?? 0),
         deleteStep: deleteStep,
         onTap: onTap,
         highlight: timeManager.step == index
        )
        .animation(.default)
        .transition(AnyTransition.slide.combined(with: .opacity).animation(.easeInOut))
        .id(step.id)
        .tag(step.id)
       }
      }
      .onChange(of: timeManager.step) { idx in
       let index = idx >= 0 ? idx : 0
       withAnimation(Animation.easeIn(duration: 0.5)) {
        reader.scrollTo((cycle.steps?.array as! [Step])[index].id, anchor: UnitPoint.init(x: 100, y: 0.66))
       }
      }
     }

Precondition failure with several MapViews
 
 
Q