Migrating from Places SDK for iOS (Legacy) to
Places Swift SDK for iOS should be straightforward and can be done
incrementally. Since structs in the Places Swift SDK for iOS are not
compatible with their Objective-C based counterparts, we recommend migrating
discrete chunks of functionality based on uses of APIs in GMSPlacesClient.

## Add the Places Swift SDK for iOS to your project

The following steps are required to use Places Swift SDK for iOS:

1. Enable the [Places API
   (New)](https://developers.google.com/maps/documentation/places/ios-sdk/cloud-setup#enabling-apis).
2. Add the [Places Swift SDK](https://developers.google.com/maps/documentation/places/ios-sdk/config.md.txt#googleplacesswift)
   to your dependencies. You can choose to install `GooglePlaces`,
   `GooglePlacesSwift`, or both.

   > [!NOTE]
   > **Note:** The GitHub URL to access Google Places Swift has changed. If you are updating a version of GooglePlacesSwift that was accessed through the old URL, https://github.com/googlemaps/ios-places-swift-sdk, remove it from your Xcode's package dependencies section.

3. Initialize the Places client with
   [`PlacesClient`](https://developers.google.com/maps/documentation/places/ios-sdk/config.md.txt#googleplacesswift_2).

## Step-by-step migration example

As an example, suppose an app using the Places SDK for iOS
receives autocomplete suggestions based on a text input, then fetches the
details of the first place suggestion. Using
Places SDK for iOS, the existing code might look something
like the following:

```swift
// Initialize Places Client.
GMSPlacesClient.provideAPIKey(apiKey)
let client = GMSPlacesClient.shared()

// Fetch Autocomplete Request.
let center = CLLocation(latitude: 37.3913916, longitude: -122.0879074)
let northEast = CLLocationCoordinate2DMake(37.388162, -122.088137)
let southWest = CLLocationCoordinate2DMake(37.395804, -122.077023)

let filter = GMSAutocompleteFilter()
filter.types = [kGMSPlaceTypeRestaurant]
filter.origin = center
filter.locationBias = GMSPlaceRectangularLocationOption(northEast, southWest)

let request = GMSAutocompleteRequest(query: "Sicilian piz")
request.filter = filter

client.fetchAutocompleteSuggestions(from: request) { (results, error) in
guard let results, error == nil else {
print("Autocomplete error: \\(String(describing: error))")
return
}
// Fetch Place Request.
guard let placeID = results.first?.placeSuggestion?.placeID else { return }
let myProperties = \[GMSPlaceProperty.name, GMSPlaceProperty.website\].map {$0.rawValue}
let fetchPlaceRequest = GMSFetchPlaceRequest(placeID: placeID, placeProperties: myProperties, sessionToken: nil)
client.fetchPlace(with: fetchPlaceRequest) { (place: GMSPlace?, error: Error?) in
guard let place, error == nil else { return }
print("Place found: \\(String(describing: place.name)); \\(String(describing: place.website))")
}
}
```

## Update the Places Client initializer

To modernize the code and take advantage of the new SDK's capabilities, you'll
need to replace the GMSPlacesClient with the PlacesClient. Additionally, the
parameter names are changed in the new method, so you'll need to update the
parameter to `from` instead of `with`. Finally, the
Places Swift SDK uses the upgraded
[AutocompleteRequest](https://developers.google.com/maps/documentation/places/ios-sdk/reference/swift/Structs/AutocompleteRequest.md.txt).

### Updated code

```swift
// Initialize Places Swift Client.
let _ = PlacesClient.provideAPIKey(apiKey)
let placesSwiftClient = PlacesClient.shared
```

### Original code

```swift
// Initialize Places Client.
GMSPlacesClient.provideAPIKey(apiKey)
let client = GMSPlacesClient.shared()
```

## Update the autocomplete request

You could begin by updating the autocomplete request flow. The old code uses a
callback to request autocomplete suggestions, while the new code employs a
`switch`/`await` pattern. Callbacks can add complexity to code structure and
error handling. The new Places Swift SDK supports concurrency,
which simplifies asynchronous operations.

```swift
// Initialize Places Swift Client.
let _ = PlacesClient.provideAPIKey(apiKey)
let placesSwiftClient = PlacesClient.shared

// Fetch Autocomplete Request.
let center = CLLocation(latitude: 37.3913916, longitude: -122.0879074)
let northEast = CLLocationCoordinate2DMake(37.388162, -122.088137)
let southWest = CLLocationCoordinate2DMake(37.395804, -122.077023)

let bias = RectangularCoordinateRegion(northEast: northEast, southWest: southWest)
let filter = AutocompleteFilter(types: [ .restaurant ], origin: center, coordinateRegionBias: bias)

let autocompleteRequest = AutocompleteRequest(query: "Sicilian piz", filter: filter)
let placeID: String
switch await placesSwiftClient.fetchAutocompleteSuggestions(with: autocompleteRequest) {
case .success(let results):
switch results.first {
case .place(let placeSuggestion):
placeID = placeSuggestion.placeID
case .none:
fallthrough
@unknown default:
return
}
case .failure(let placesError):
print("Autocomplete error: \\(placesError)")
return
}

// Initialize Places Client.
GMSPlacesClient.provideAPIKey(apiKey)
let placesClient = GMSPlacesClient.shared()

// Fetch Place Request.
let myProperties = [GMSPlaceProperty.name, GMSPlaceProperty.website].map {$0.rawValue}

let fetchPlaceRequest = GMSFetchPlaceRequest(placeID: placeID, placeProperties: myProperties, sessionToken: nil)

placesClient.fetchPlace(with: fetchPlaceRequest) { (place: GMSPlace?, error: Error?) in
  guard let place, error == nil else { return }
  print("Place found: \(String(describing: place.name)); \(String(describing: place.website))")
}
```

## Replace deprecated classes, methods, and typedefs

The following classes, methods, and typedefs in the Places SDK for iOS are no longer available in the v11.0 version and later.

This table shows the deprecated methods and their replacements:

| Deprecated | Replacement |
|---|---|
| `currentPlaceWithCallback` or `findPlaceLikelihoodsFromCurrentLocationWithPlaceFields` | `searchNearbyWithRequest` |
| `lookUpPlaceID` or `fetchPlaceFromPlaceID` | `fetchPlaceWithRequest` |
| `lookUpPhotosForPlaceID` or `loadPlacePhoto` | `fetchPhotoWithRequest` |
| `GMSAutocompletePrediction` | `AutocompleteSuggestion` |
| `findAutocompletePredictionsFromQuery` or `GMSAutocompleteFetcher` | `fetchAutocompleteSuggestionsFromRequest` |
| `isOpenWithPlaceID` or `isOpenWithPlace` | `isOpenWithRequest` |
| `GMSAutocompleteResultsViewController`, `GMSAutocompleteTableDataSource`, or `GMSAutocompleteViewController` | `placeAutocomplete` |

## Update method and class names

Finally, complete the migration by refactoring the `fetchPlace` code and
removing both the `GMSPlacesClient` initialization and `GMSPlaceProperty`
declaration. In Places Swift SDK, the method and classnames
have been updated to remove the "GMS" prefix, and must be updated accordingly;
e.g., `GMSFetchPlaceRequest` becomes `FetchPlaceRequest`.

### Type-handling

The new `fetchPlace` method uses improved type handling. While the old code
required passing the property's raw values, the new code doesn't require
developers to explicitly fetch raw values here, thereby improving concision and
readability.

### Concurrency

Additionally, the new method supports concurrency, allowing for replacing the
callback in `placesClient.fetchPlace` with a `switch`/`await` pattern in
`placesSwiftClient.fetchPlace`.

```swift
// Initialize Places Swift Client.
let _ = PlacesClient.provideAPIKey(apiKey)
let placesSwiftClient = PlacesClient.shared

// Fetch Autocomplete Request.
let center = CLLocation(latitude: 37.3913916, longitude: -122.0879074)
let northEast = CLLocationCoordinate2DMake(37.388162, -122.088137)
let southWest = CLLocationCoordinate2DMake(37.395804, -122.077023)

let bias = RectangularCoordinateRegion(northEast: northEast, southWest: southWest)
let filter = AutocompleteFilter(types: [ .restaurant ], origin: center, coordinateRegionBias: bias)

let autocompleteRequest = AutocompleteRequest(query: "Sicilian piz", filter: filter)
let placeID: String
switch await placesSwiftClient.fetchAutocompleteSuggestions(with: autocompleteRequest) {
case .success(let results):
  switch results.first {
  case .place(let placeSuggestion):
    placeID = placeSuggestion.placeID
  case .none:
    fallthrough
  @unknown default:
    return
  }
case .failure(let placesError):
  print("Autocomplete error: \(placesError)")
  return
}

// Fetch Place Request.
let fetchPlaceRequest = FetchPlaceRequest(placeID: placeID, placeProperties: \[.displayName, .websiteURL\])
switch await placesSwiftClient.fetchPlace(with: fetchPlaceRequest) {
case .success(let place):
print("Place found: \\(place.displayName): \\(String(describing: place.description))")
case .failure(let placesError):
print("Place not found: \\(placeID); \\(placesError)")
}
```

## Stay up-to-date

Visit the [release notes page for Places Swift SDK for iOS](https://developers.google.com/maps/documentation/places/ios-sdk/places-swift-release-notes.md.txt) to learn
about new features and changes.