Building Engaging User Interfaces with SwiftUI

Mar 12 2025 · Swift 5.9, iOS 17.0, XCode 15.0

Lesson 03: Integrating SwiftUI with UIKit

Building a Coordinator Class

Episode complete

Play next episode

Next

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Connecting Delegates, Data Sources, and More

If you’re familiar with MKMap in iOS, you might wonder how you provide the delegate to add overlays to this MKMapView. If you try accessing data in a SwiftUI struct directly from UIKit, your app crashes. Instead, you have to create a Coordinator class that inherits from NSObject.

func makeUIView(context: Context) -> MKMapView {
  MKMapView(frame: .zero)
}
class MapCoordinator: NSObject {
  var mapView: FlightMapView
  var fraction: CGFloat

  init(
    _ mapView: FlightMapView,
    progress: CGFloat = 0.0
  ) {
    self.mapView = mapView
    self.fraction = progress
  }
}
func makeCoordinator() -> MapCoordinator {
  MapCoordinator(self, progress: progress)
}
// 1
let distance = startPoint.distance(to: endPoint)
let cityRadius = distance / 100.0

// 2
let startOverlay = MKCircle(
  center: startCoordinate,
  radius: cityRadius
)

let endOverlay = MKCircle(
  center: endCoordinate,
  radius: cityRadius
)

// 3
let flightPath = MKGeodesicPolyline(
  coordinates: [startCoordinate, endCoordinate],
  count: 2
)

// 4
view.addOverlays([startOverlay, endOverlay, flightPath])
extension MapCoordinator: MKMapViewDelegate {
  func mapView(
    _ mapView: MKMapView,
    rendererFor overlay: MKOverlay
  ) -> MKOverlayRenderer {
    // 1
    if overlay is MKCircle {
      let renderer = MKCircleRenderer(overlay: overlay)
      renderer.fillColor = UIColor.black
      renderer.strokeColor = UIColor.black
      return renderer
    }

    // 2
    if overlay is MKGeodesicPolyline {
      let renderer = MKPolylineRenderer(overlay: overlay)
      renderer.strokeColor = UIColor(
        red: 0.0,
        green: 0.0,
        blue: 1.0,
        alpha: 0.3
      )
      // 3
      renderer.lineWidth = 3.0
      renderer.strokeStart = 0.0
      renderer.strokeEnd = fraction
      return renderer
    }

    return MKOverlayRenderer()
  }
}
func makeUIView(context: Context) -> MKMapView {
  let view = MKMapView(frame: .zero)
  view.delegate = context.coordinator
  return view
}
FlightMapView(
  startCoordinate: flight.startingAirportLocation,
  endCoordinate: flight.endingAirportLocation,
  progress: flightTimeFraction(
    flight: flight
  )
)
.frame(width: 300, height: 300)
See forum comments
Cinema mode Download course materials from Github
Previous: Integrating SwiftUI with UIKit Next: Conclusion