SwiftUI (Swift) ile iOS uygulamanıza harita ekleme

1. Başlamadan Önce

Bu codelab'de, iOS için Haritalar SDK'sını SwiftUI ile nasıl kullanacağınız açıklanmaktadır.

screenshot-iphone-12-black@2x.png

Ön koşullar

  • Temel Swift bilgisi
  • SwiftUI ile ilgili temel bilgiler

Yapacaklarınız

  • SwiftUI kullanarak bir iOS uygulamasına Google Haritalar eklemek için iOS için Haritalar SDK'sını etkinleştirin ve kullanın.
  • Haritaya işaretçi ekleyin.
  • SwiftUI ile GMSMapView nesnesi arasında durumu aktarma.

İhtiyacınız olanlar

2. Hazırlanın

Aşağıdaki etkinleştirme adımı için iOS için Haritalar SDK'sını etkinleştirin.

Google Haritalar Platformu'nu ayarlama

Henüz bir Google Cloud Platform hesabınız ve faturalandırmanın etkinleştirildiği bir projeniz yoksa lütfen faturalandırma hesabı ve proje oluşturmak için Google Haritalar Platformu'nu Kullanmaya Başlama kılavuzuna bakın.

  1. Cloud Console'da proje açılır menüsünü tıklayın ve bu codelab için kullanmak istediğiniz projeyi seçin.

  1. Bu codelab için gereken Google Haritalar Platformu API'lerini ve SDK'larını Google Cloud Marketplace'te etkinleştirin. Bunun için bu videodaki veya bu dokümandaki adımları uygulayın.
  2. Cloud Console'un Kimlik Bilgileri sayfasında bir API anahtarı oluşturun. Bu videodaki veya bu dokümandaki adımları uygulayabilirsiniz. Google Haritalar Platformu'na yapılan tüm istekler için API anahtarı gerekir.

3. Başlangıç kodunu indirme

Mümkün olduğunca hızlı bir şekilde başlamanıza yardımcı olmak için bu codelab'i takip etmenize yardımcı olacak başlangıç kodunu aşağıda bulabilirsiniz. Çözüme geçebilirsiniz ancak kendiniz oluşturmak için tüm adımları takip etmek istiyorsanız okumaya devam edin.

  1. git yüklüyse depoyu klonlayın.
git clone https://github.com/googlecodelabs/maps-ios-swiftui.git

Alternatif olarak, kaynak kodunu indirmek için aşağıdaki düğmeyi tıklayabilirsiniz.

  1. Kodu aldıktan sonra bir terminalde cd komutunu kullanarak starter/GoogleMapsSwiftUI dizinine gidin.
  2. iOS için Haritalar SDK'sını indirmek üzere carthage update --platform iOS komutunu çalıştırın.
  3. Son olarak, GoogleMapsSwiftUI.xcodeproj dosyasını Xcode'da açın.

4. Koda Genel Bakış

İndirdiğiniz başlangıç projesinde aşağıdaki sınıflar sizin için sağlanmış ve uygulanmıştır:

  • AppDelegate - the application's UIApplicationDelegate. iOS için Haritalar SDK'sının başlatılacağı yer burasıdır.
  • City - Bir şehri temsil eden yapı (şehrin adını ve koordinatını içerir).
  • Google Harita (GMSMapView) içeren MapViewController - kapsamı daraltılmış bir UIKit UIViewController
    • SceneDelegate: ContentView öğesinin oluşturulduğu uygulamanın UIWindowSceneDelegate.

Ayrıca, aşağıdaki sınıflar kısmen uygulanmıştır ve bu codelab'in sonunda sizin tarafınızdan tamamlanacaktır:

  • ContentView - Uygulamanızı içeren üst düzey SwiftUI görünümü.
  • MapViewControllerBridge - UIKit görünümünü SwiftUI görünümüne bağlayan bir sınıf. Bu sınıf, SwiftUI'da MapViewController erişilebilirliğini sağlar.

5. SwiftUI ve UIKit karşılaştırması

SwiftUI, iOS uygulamaları geliştirmek için iOS 13'te UIKit'e alternatif bir kullanıcı arayüzü çerçevesi olarak tanıtıldı. Önceki sürümü UIKit'e kıyasla SwiftUI'ın çeşitli avantajları vardır. Örneğin:

  • Durum değiştiğinde görünümler otomatik olarak güncellenir. State adı verilen nesneler kullanıldığında, içerdiği temel değerde yapılan herhangi bir değişiklik kullanıcı arayüzünün otomatik olarak güncellenmesine neden olur.
  • Canlı önizlemeler sayesinde daha hızlı geliştirme yapabilirsiniz. Canlı önizlemeler, SwiftUI görünümünün önizlemesi Xcode'da kolayca görülebildiğinden görsel değişiklikleri görmek için kodu oluşturup bir emülatöre dağıtma ihtiyacını en aza indirir.
  • Doğru kaynağı Swift'te bulabilirsiniz. SwiftUI'daki tüm görünümler Swift'te bildirildiğinden artık Interface Builder'ı kullanmak gerekmez.
  • UIKit ile birlikte çalışır. UIKit ile birlikte çalışabilirlik, mevcut uygulamaların mevcut görünümleriyle birlikte kademeli olarak SwiftUI kullanabilmesini sağlar. Ayrıca, iOS için Haritalar SDK'sı gibi henüz SwiftUI'ı desteklemeyen kitaplıklar da SwiftUI'da kullanılabilir.

Ancak bazı dezavantajları da vardır:

  • SwiftUI yalnızca iOS 13 veya sonraki sürümlerde kullanılabilir.
  • Görünüm hiyerarşisi, Xcode önizlemelerinde incelenemez.

SwiftUI State and data flow

SwiftUI, bildirim temelli bir yaklaşım kullanarak kullanıcı arayüzü oluşturmak için yeni bir yol sunar. SwiftUI'a görünümünüzün nasıl görünmesini istediğinizi ve tüm farklı durumlarını söylersiniz, sistem de gerisini halleder. SwiftUI, temel durum bir etkinlik veya kullanıcı işlemi nedeniyle her değiştiğinde görünümü günceller. Bu tasarım genellikle tek yönlü veri akışı olarak adlandırılır. Bu tasarımın ayrıntıları bu codelab'in kapsamı dışında olsa da Apple'ın Durum ve Veri Akışı dokümanında bu tasarımın işleyiş şekli hakkında bilgi edinmenizi öneririz.

UIViewRepresentable veya UIViewControllerRepresentable kullanarak UIKit ve SwiftUI'yi köprüleme

iOS için Haritalar SDK'sı UIKit üzerine kurulu olduğundan ve SwiftUI ile uyumlu bir görünüm sağlamadığından, SwiftUI'da kullanmak için UIViewRepresentable veya UIViewControllerRepresentable'ye uymanız gerekir. Bu protokoller, SwiftUI'ın sırasıyla UIKit ile oluşturulmuş UIView ve UIViewController öğelerini içermesini sağlar. SwiftUI görünümüne Google Haritası eklemek için iki protokolü de kullanabilirsiniz. Ancak bir sonraki adımda, harita içeren bir UIViewController eklemek için UIViewControllerRepresentable kullanmayı inceleyeceğiz.

6. Harita ekleme

Bu bölümde, Google Haritalar'ı bir SwiftUI görünümüne ekleyeceksiniz.

add-a-map-screenshot@2x.png

API anahtarınızı ekleme

Hesabınızı uygulamada gösterilecek haritayla ilişkilendirmek için önceki bir adımda oluşturduğunuz API anahtarının iOS için Haritalar SDK'sına sağlanması gerekir.

API anahtarınızı sağlamak için AppDelegate.swift dosyasını açın ve application(_, didFinishLaunchingWithOptions) yöntemine gidin. SDK, "YOUR_API_KEY" dizesiyle GMSServices.provideAPIKey() kullanılarak başlatılır. Bu dizeyi API anahtarınızla değiştirin. Bu adımı tamamladığınızda uygulama başlatılırken iOS için Haritalar SDK'sı başlatılır.

MapViewControllerBridge kullanarak Google Haritası ekleme

API anahtarınız SDK'ya sağlandığına göre, bir sonraki adım haritayı uygulamada göstermektir.

Başlangıç kodunda sağlanan görünüm denetleyicisi MapViewController, görünümünde GMSMapView içerir. Ancak bu görünüm denetleyicisi UIKit'te oluşturulduğundan, ContentView içinde kullanılabilmesi için bu sınıfı SwiftUI'ye köprülemeniz gerekir. Bunu yapmak için:

  1. Dosyayı MapViewControllerBridge Xcode'da açın.

Bu sınıf, bir UIKit UIViewController öğesini sarmalayarak SwiftUI görünümü olarak kullanılabilmesi için gereken UIViewControllerRepresentable protokolüne uygundur. Başka bir deyişle, bu protokole uymak bir UIKit görünümünü SwiftUI görünümüne bağlamayı kolaylaştırır. Bu protokole uymak için iki yöntemin uygulanması gerekir:

  • makeUIViewController(context) - Bu yöntem, temel UIViewController öğesini oluşturmak için SwiftUI tarafından çağrılır. UIViewController öğenizi burada oluşturur ve ilk durumunu iletirsiniz.
  • updateUIViewController(_, context): Bu yöntem, durum her değiştiğinde SwiftUI tarafından çağrılır. Durum değişikliğine yanıt vermek için temel UIViewController üzerinde değişiklik yapmanız gerekir.
  1. MapViewController oluşturun

makeUIViewController(context) işlevinin içinde yeni bir MapViewController oluşturun ve bunu sonuç olarak döndürün. Bu işlemi yaptıktan sonra MapViewControllerBridge şu şekilde görünmelidir:

MapViewControllerBridge

import GoogleMaps
import SwiftUI

struct MapViewControllerBridge: UIViewControllerRepresentable {

  func makeUIViewController(context: Context) -> MapViewController {
    return MapViewController()
  }

  func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
  }
}

ContentView'da MapViewControllerBridge'i kullanma

MapViewControllerBridge, MapViewController örneğini oluşturduğuna göre bir sonraki adım, harita görüntülemek için bu yapıyı ContentView içinde kullanmaktır.

  1. Dosyayı ContentView Xcode'da açın.

ContentView, SceneDelegate içinde oluşturulur ve üst düzey uygulama görünümünü içerir. Harita bu dosyanın içinden eklenir.

  1. body mülkünde bir MapViewControllerBridge oluşturun.

Bu dosyanın body özelliği kapsamında sizin için ZStack sağlanmış ve uygulanmıştır. ZStack, sonraki bir adımda kullanacağınız, etkileşimli ve sürüklenebilir bir şehir listesi içerir. Şimdilik, şehir listesi görünümünün arkasında uygulamada bir harita gösterilmesi için ZStack öğesinin ilk alt görünümü olarak MapViewControllerBridge oluşturun.ZStack Bu işlemden sonra ContentView içindeki body özelliğinin içeriği şu şekilde görünmelidir:

ContentView

var body: some View {

  let scrollViewHeight: CGFloat = 80

  GeometryReader { geometry in
    ZStack(alignment: .top) {
      // Map
      MapViewControllerBridge()

      // Cities List
      CitiesList(markers: $markers) { (marker) in
        guard self.selectedMarker != marker else { return }
        self.selectedMarker = marker
        self.zoomInCenter = false
        self.expandList = false
      }  handleAction: {
        self.expandList.toggle()
      } // ...
    }
  }
}
  1. Şimdi uygulamayı çalıştırın. Haritanın cihazınızın ekranında yüklendiğini ve ekranın alt kısmında şehirlerin bulunduğu, sürüklenebilir bir liste göreceksiniz.

7. Haritaya işaretçi ekleme

Önceki adımda, şehir listesini gösteren etkileşimli bir listenin yanına harita eklediniz. Bu bölümde, listedeki her şehir için işaretçi ekleyeceksiniz.

map-with-markers@2x.png

Durum olarak işaretçiler

ContentView, markers adlı bir özellik bildirir. Bu özellik, cities statik özelliğinde bildirilen her şehri temsil eden GMSMarker listesidir. Bu özelliğin, SwiftUI tarafından yönetilmesi gerektiğini belirtmek için SwiftUI özellik sarmalayıcısı State ile açıklama eklenmiş olduğunu unutmayın. Bu nedenle, bu mülkte herhangi bir değişiklik algılanırsa (ör. işaretçi ekleme veya kaldırma) bu durumu kullanan görünümler güncellenir.

ContentView

  static let cities = [
    City(name: "San Francisco", coordinate: CLLocationCoordinate2D(latitude: 37.7576, longitude: -122.4194)),
    City(name: "Seattle", coordinate: CLLocationCoordinate2D(latitude: 47.6131742, longitude: -122.4824903)),
    City(name: "Singapore", coordinate: CLLocationCoordinate2D(latitude: 1.3440852, longitude: 103.6836164)),
    City(name: "Sydney", coordinate: CLLocationCoordinate2D(latitude: -33.8473552, longitude: 150.6511076)),
    City(name: "Tokyo", coordinate: CLLocationCoordinate2D(latitude: 35.6684411, longitude: 139.6004407))
  ]

  /// State for markers displayed on the map for each city in `cities`
  @State var markers: [GMSMarker] = cities.map {
    let marker = GMSMarker(position: $0.coordinate)
    marker.title = $0.name
    return marker
  }

ContentView, şehir listesini oluşturmak için markers özelliğini CitiesList sınıfına ileterek kullandığını unutmayın.

CitiesList

struct CitiesList: View {

  @Binding var markers: [GMSMarker]

  var body: some View {
    GeometryReader { geometry in
      VStack(spacing: 0) {
        // ...
        // List of Cities
        List {
          ForEach(0..<self.markers.count) { id in
            let marker = self.markers[id]
            Button(action: {
              buttonAction(marker)
            }) {
              Text(marker.title ?? "")
            }
          }
        }.frame(maxWidth: .infinity)
      }
    }
  }
}

@Binding kullanarak durumu MapViewControllerBridge'e aktarın.

markers özelliğinden gelen verileri gösteren şehir listesine ek olarak, bu özelliği MapViewControllerBridge yapısına iletin. Böylece bu özellik, işaretçileri haritada göstermek için kullanılabilir. Bunu yapmak için:

  1. MapViewControllerBridge içinde @Binding ile ek açıklama eklenmiş yeni bir markers özelliği bildirin.

MapViewControllerBridge

struct MapViewControllerBridge: : UIViewControllerRepresentable {
  @Binding var markers: [GMSMarker]
  // ...
}
  1. MapViewControllerBridge içinde, markers özelliğini kullanmak için updateUIViewController(_, context) yöntemini güncelleyin.

Önceki adımda belirtildiği gibi, durum her değiştiğinde SwiftUI tarafından updateUIViewController(_, context) çağrılır. Haritayı bu yöntemle güncellemek ve işaretçileri markers içinde göstermek istiyoruz. Bunu yapmak için her işaretçinin map özelliğini güncellemeniz gerekir. Bu adımı tamamladıktan sonra MapViewControllerBridge aşağıdaki gibi görünmelidir:

import GoogleMaps
import SwiftUI

struct MapViewControllerBridge: UIViewControllerRepresentable {

  @Binding var markers: [GMSMarker]

  func makeUIViewController(context: Context) -> MapViewController {
    return MapViewController()
  }

  func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
    // Update the map for each marker
    markers.forEach { $0.map = uiViewController.map }
  }
}
  1. markers özelliğini ContentView öğesinden MapViewControllerBridge öğesine iletme

MapViewControllerBridge içinde yeni bir özellik eklediğiniz için artık bu özelliğin değerinin MapViewControllerBridge başlatıcısında iletilmesi gerekiyor. Bu nedenle, uygulamayı oluşturmaya çalıştığınızda derlenmediğini fark edersiniz. Bu sorunu düzeltmek için MapViewControllerBridge öğesinin oluşturulduğu ContentView bölümünde bir güncelleme yapın ve markers özelliğini şu şekilde iletin:

struct ContentView: View {
  // ...
  var body: some View {
    // ...
    GeometryReader { geometry in
      ZStack(alignment: .top) {
        // Map
        MapViewControllerBridge(markers: $markers)
        // ...
      }
    }
  }
}

MapViewControllerBridge, bağlı bir özellik beklediğinden markers değerini iletmek için $ önekini kullandığımıza dikkat edin. $, Swift özellik sarmalayıcılarıyla kullanılmak üzere ayrılmış bir önek. Bir duruma uygulandığında Binding döndürür.

  1. Haritada gösterilen işaretçileri görmek için uygulamayı çalıştırın.

8. Animasyonu seçili bir şehre kadar oynatma

Önceki adımda, bir SwiftUI görünümünden diğerine State aktararak haritaya işaretçiler eklediniz. Bu adımda, etkileşimli listede dokunulduktan sonra bir şehri veya işaretçiyi canlandıracaksınız. Animasyonu gerçekleştirmek için, değişiklik meydana geldiğinde haritanın kamera konumunu değiştirerek bir durumdaki değişikliklere tepki verirsiniz. Haritanın kamerası kavramı hakkında daha fazla bilgi edinmek için Kamera ve Görünüm başlıklı makaleyi inceleyin.

animate-city@2x.png

Haritayı seçili şehre göre animasyonla hareket ettirme

Haritayı seçili bir şehre göre animasyonla göstermek için:

  1. MapViewControllerBridge içinde yeni bir bağlama tanımlayın

ContentView, nil olarak başlatılan ve listede bir şehir seçildiğinde güncellenen selectedMarker adlı bir State özelliğine sahiptir. Bu, ContentView içindeki CitiesList görünümü buttonAction tarafından işlenir.

ContentView

CitiesList(markers: $markers) { (marker) in
  guard self.selectedMarker != marker else { return }
  self.selectedMarker = marker
  // ...
}

selectedMarker her değiştiğinde MapViewControllerBridge, haritayı seçili işaretçiye göre canlandırabilmek için bu durum değişikliğinden haberdar olmalıdır. Bu nedenle, MapViewControllerBridge içinde GMSMarker türünde yeni bir Bağlama tanımlayın ve özelliğe selectedMarker adını verin.

MapViewControllerBridge

struct MapViewControllerBridge: UIViewControllerRepresentable {
  @Binding var selectedMarker: GMSMarker?
}
  1. selectedMarker değiştiğinde haritayı animasyonlu hale getirmek için MapViewControllerBridge öğesini güncelleyin.

Yeni bir Bağlama bildirildikten sonra, haritanın seçilen işaretçiye göre animasyon oluşturması için MapViewControllerBridge'nın updateUIViewController_, context) işlevini güncellemeniz gerekir. Aşağıdaki kodu kopyalayarak bu işlemi yapabilirsiniz:

struct MapViewControllerBridge: UIViewControllerRepresentable {
  @Binding var selectedMarker: GMSMarker?

  func updateUIViewController(_ uiViewController: MapViewController, context: Context) {
    markers.forEach { $0.map = uiViewController.map }
    selectedMarker?.map = uiViewController.map
    animateToSelectedMarker(viewController: uiViewController)
  }

  private func animateToSelectedMarker(viewController: MapViewController) {
    guard let selectedMarker = selectedMarker else {
      return
    }

    let map = viewController.map
    if map.selectedMarker != selectedMarker {
      map.selectedMarker = selectedMarker
      DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        map.animate(toZoom: kGMSMinZoomLevel)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
          map.animate(with: GMSCameraUpdate.setTarget(selectedMarker.position))
          DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
            map.animate(toZoom: 12)
          })
        }
      }
    }
  }
}

animateToSelectedMarker(viewController) işlevi, GMSMapView'nin animate(with) işlevini kullanarak bir dizi harita animasyonu gerçekleştirir.

  1. ContentView kullanıcısının selectedMarker kartını MapViewControllerBridge kullanıcısına aktarma

MapViewControllerBridge yeni bağlamayı bildirdikten sonra ContentView öğesini güncelleyerek MapViewControllerBridge öğesinin oluşturulduğu selectedMarker öğesini iletin.

ContentView

struct ContentView: View {
  // ...
  var body: some View {
    // ...
    GeometryReader { geometry in
      ZStack(alignment: .top) {
        // Map
        MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker)
        // ...
      }
    }
  }
}

Bu adımı tamamladığınızda listede yeni bir şehir seçildiğinde harita animasyonlu hale gelir.

Şehri vurgulamak için SwiftUI görünümünü canlandırma

SwiftUI, durum geçişleri için animasyonları gerçekleştirme işlemini ele alacağından görünümlere animasyon ekleme sürecini basitleştirir. Bunu göstermek için, harita animasyonu tamamlandıktan sonra görünümü seçilen şehre odaklayarak daha fazla animasyon ekleyeceksiniz. Bunu yapmak için aşağıdaki adımları uygulayın:

  1. MapViewControllerBridge hizmetine onAnimationEnded kapanışı ekleme

SwiftUI animasyonu, daha önce eklediğiniz harita animasyonu dizisinden sonra gerçekleştirileceğinden onAnimationEnded adlı yeni bir kapatma MapViewControllerBridge içinde bildirin ve bu kapatmayı animateToSelectedMarker(viewController) yöntemindeki son harita animasyonundan 0,5 saniye sonra çağırın.

MapViewControllerBridge

struct MapViewControllerBridge: UIViewControllerRepresentable {
    var onAnimationEnded: () -> ()

    private func animateToSelectedMarker(viewController: MapViewController) {
    guard let selectedMarker = selectedMarker else {
      return
    }

    let map = viewController.map
    if map.selectedMarker != selectedMarker {
      map.selectedMarker = selectedMarker
      DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
        map.animate(toZoom: kGMSMinZoomLevel)
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
          map.animate(with: GMSCameraUpdate.setTarget(selectedMarker.position))
          DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
            map.animate(toZoom: 12)
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.5, execute: {
              // Invoke onAnimationEnded() once the animation sequence completes
              onAnimationEnded()
            })
          })
        }
      }
    }
  }
}
  1. MapViewControllerBridge içinde onAnimationEnded uygulayın

onAnimationEnded kapatmasını, MapViewControllerBridge öğesinin ContentView içinde örneklendirildiği yerde uygulayın. zoomInCenter adlı yeni bir durum ekleyen ve clipShape kullanarak görünümü değiştiren, ayrıca zoomInCenter değerine bağlı olarak kırpılmış şeklin çapını değiştiren aşağıdaki kodu kopyalayıp yapıştırın.

ContentView

struct ContentView: View {
  @State var zoomInCenter: Bool = false
  // ...
  var body: some View {
    // ...
    GeometryReader { geometry in
      ZStack(alignment: .top) {
        // Map
        let diameter = zoomInCenter ? geometry.size.width : (geometry.size.height * 2)
        MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker, onAnimationEnded: {
          self.zoomInCenter = true
        })
        .clipShape(
           Circle()
             .size(
               width: diameter,
               height: diameter
             )
             .offset(
               CGPoint(
                 x: (geometry.size.width - diameter) / 2,
                 y: (geometry.size.height - diameter) / 2
               )
             )
        )
        .animation(.easeIn)
        .background(Color(red: 254.0/255.0, green: 1, blue: 220.0/255.0))
      }
    }
  }
}
  1. Animasyonları görmek için uygulamayı çalıştırın.

9. SwiftUI'a etkinlik gönderme

Bu adımda, GMSMapView tarafından yayınlanan etkinlikleri dinleyecek ve bu etkinliği SwiftUI'ye göndereceksiniz. Özellikle, harita görünümüne bir temsilci atayacak ve kamera hareket etkinliklerini dinleyeceksiniz. Böylece, bir şehre odaklanıldığında ve harita kamerası bir hareketle hareket ettiğinde harita görünümünün odağı kaldırılacak ve haritanın daha fazlasını görebileceksiniz.

SwiftUI Koordinatörlerini Kullanma

GMSMapView, kamera konumundaki değişiklikler veya bir işaretçiye dokunulması gibi etkinlikler yayınlar. Bu etkinlikleri dinleme mekanizması GMSMapViewDelegate protokolü aracılığıyla sağlanır. SwiftUI, özellikle UIKit görünüm denetleyicileri için temsilci olarak hareket etmek üzere kullanılan bir Koordinatör kavramını sunar. Bu nedenle, SwiftUI dünyasında bir Coordinator, GMSMapViewDelegate protokolüne uygunluktan sorumlu olmalıdır. Bunun için aşağıdaki adımları uygulayın:

  1. MapViewControllerBridge içinde MapViewCoordinator adlı bir Düzenleyici oluşturun.

MapViewControllerBridge sınıfının içinde iç içe yerleştirilmiş bir sınıf oluşturun ve bu sınıfa MapViewCoordinator adını verin. Bu sınıf, GMSMapViewDelegate ile uyumlu olmalı ve MapViewControllerBridge özelliğini bildirmelidir.

MapViewControllerBridge

struct MapViewControllerBridge: UIViewControllerRepresentable {
  // ...
  final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
    var mapViewControllerBridge: MapViewControllerBridge

    init(_ mapViewControllerBridge: MapViewControllerBridge) {
      self.mapViewControllerBridge = mapViewControllerBridge
    }
  }
}
  1. MapViewControllerBridge içinde makeCoordinator() uygulayın

Ardından, makeCoordinator() yöntemini MapViewControllerBridge içinde uygulayın ve önceki adımda oluşturduğunuz MapViewCoodinator öğesinin bir örneğini döndürün.

MapViewControllerBridge

struct MapViewControllerBridge: UIViewControllerRepresentable {
  // ...
  func makeCoordinator() -> MapViewCoordinator {
    return MapViewCoordinator(self)
  }
}
  1. MapViewCoordinator öğesini harita görünümünün temsilcisi olarak ayarlayın.

Özel koordinatör oluşturulduktan sonraki adım, koordinatörü görünüm denetleyicisinin harita görünümü için temsilci olarak ayarlamaktır. Bunu yapmak için makeUIViewController(context) içinde görünüm denetleyicisi başlatmayı güncelleyin. Önceki adımda oluşturulan koordinatöre Context nesnesinden erişilebilir.

MapViewControllerBridge

struct MapViewControllerBridge: UIViewControllerRepresentable {
  // ...
  func makeUIViewController(context: Context) -> MapViewController {
    let uiViewController = MapViewController()
    uiViewController.map.delegate = context.coordinator
    return uiViewController
  }
}
  1. Kamera hareket etkinliğinin yukarıya yayılması için MapViewControllerBridge öğesine kapatma ekleyin.

Amaç, görünümü kamera hareketleriyle güncellemek olduğundan MapViewControllerBridge içinde mapViewWillMove adlı bir boolean kabul eden yeni bir kapatma özelliği bildirin ve bu kapatmayı MapViewCoordinator içindeki temsilci yönteminde mapView(_, willMove) çağırın. SwiftUI görünümünün yalnızca hareketle ilgili kamera hareket etkinliklerine tepki verebilmesi için gesture değerini kapatmaya iletin.

MapViewControllerBridge

struct MapViewControllerBridge: UIViewControllerRepresentable {
  var mapViewWillMove: (Bool) -> ()
  //...

  final class MapViewCoordinator: NSObject, GMSMapViewDelegate {
    // ...
    func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
      self.mapViewControllerBridge.mapViewWillMove(gesture)
    }
  }
}
  1. ContentView'i, mapWillMove için bir değer iletilecek şekilde güncelleyin.

MapViewControllerBridge tarihinde yeni bir kapanış ilan edildiğinden ContentView parametresini, bu yeni kapanış için bir değer iletecek şekilde güncelleyin. Bu kapatma işleminde, taşıma etkinliği bir hareketle ilgiliyse Durum'u zoomInCenter konumundan false konumuna getirin. Bu işlem, harita bir hareketle taşındığında haritayı tekrar tam görünümde gösterir.

ContentView

struct ContentView: View {
  @State var zoomInCenter: Bool = false
  // ...
  var body: some View {
    // ...
    GeometryReader { geometry in
      ZStack(alignment: .top) {
        // Map
        let diameter = zoomInCenter ? geometry.size.width : (geometry.size.height * 2)
        MapViewControllerBridge(markers: $markers, selectedMarker: $selectedMarker, onAnimationEnded: {
          self.zoomInCenter = true
        }, mapViewWillMove: { (isGesture) in
          guard isGesture else { return }
          self.zoomInCenter = false
        })
        // ...
      }
    }
  }
}
  1. Yeni değişiklikleri görmek için uygulamayı çalıştırın.

10. Tebrikler

Bu aşamaya ulaştığınız için tebrik ederiz. Çok şey öğrendiniz. Umuyoruz ki öğrendikleriniz sayesinde artık iOS için Haritalar SDK'sını kullanarak kendi SwiftUI uygulamanızı oluşturabilirsiniz.

Öğrendikleriniz

  • SwiftUI ile UIKit arasındaki farklar
  • UIViewControllerRepresentable kullanarak SwiftUI ile UIKit arasında köprü kurma
  • State ve Binding ile harita görünümünde değişiklik yapma
  • Coordinator kullanarak harita görünümünden SwiftUI'a etkinlik gönderme

Sırada ne var?

  • iOS için Haritalar SDK'sı
    • iOS için Haritalar SDK'sının resmi dokümanları
  • iOS için Yerler SDK'sı: Çevrenizdeki yerel işletmeleri ve ilgi çekici yerleri bulma
  • maps-sdk-for-ios-samples
    • GitHub'da, iOS için Haritalar SDK'sındaki tüm özellikleri gösteren örnek kod.
  • SwiftUI: Apple'ın SwiftUI ile ilgili resmi belgeleri
  • Aşağıdaki anketi yanıtlayarak en yararlı bulacağınız içerikleri oluşturmamıza yardımcı olun:

Başka hangi codelab'leri görmek istersiniz?

Haritalarda veri görselleştirme Haritalarımın stilini özelleştirme hakkında daha fazla bilgi Haritalarda 3D etkileşimler için geliştirme

En çok ilgilendiğiniz codelab'i bulamıyor musunuz? Buradan yeni bir sorunla ilgili istekte bulunun.