SwiftyH3 โฌก

November 22, 2025 ยท View on GitHub

The Swifty way to use Uber's H3 geospatial indexing system.

Documentation Swift versions Swift platforms

Quick Start

import SwiftyH3

// Find the containing cell for a given location
let latlng = H3LatLng(latitudeDegs: 37.7955, longitudeDegs: -122.3937)
let cell = try! latlng.cell(at: .res10)
print(cell) // 8a283082a677fff

// Retrieve the center of the cell (as H3LatLng or CLLocationCoordinate2D)
let coordinate: CLLocationCoordinate2D = try! cell.center.coordinates

// Find the bounds of this cell
let bounds: [H3LatLng] = try! cell.boundary

Installation

Swift Package Manager

Add the following line to your package's Package.swift file:

.package(url: "https://github.com/pawelmajcher/SwiftyH3.git", "0.5.0"..<"0.6.0")

Xcode

Go to File > Add Package Dependencies... and enter https://github.com/pawelmajcher/SwiftyH3.git in the upper-right corner.

H3 API support

Indexing functions

H3 C functionExample SwiftyH3 codeDocs
latLngToCelltry H3LatLng(latitudeDegs: 37.7955, longitudeDegs: -122.3937).cell(at: .res8)๐Ÿ“–
cellToLatLngtry H3Cell("8a283082a677fff")!.center๐Ÿ“–
cellToBoundarytry H3Cell("8a283082a677fff")!.boundary๐Ÿ“–

Index inspection functions

H3 C functionExample SwiftyH3 codeDocs
getResolutiontry H3DirectedEdge("115283473fffffff")!.resolution๐Ÿ“–
getBaseCellNumbertry H3Vertex("22528340bfffffff")!.baseCellNumber๐Ÿ“–
getIndexDigittry H3Vertex("22528340bfffffff")!.digit(for: .res2)๐Ÿ“–
constructCelltry H3Cell(base: 20, [0, 6, 0, 4, 0, 5])๐Ÿ“–
stringToH3H3Cell("8a283082a677fff")!๐Ÿ“–
h3ToStringtry H3Cell(599686042433355775).description๐Ÿ“–
isValidCellcell.isValid๐Ÿ“–
isValidIndexcell.isSomeH3Index๐Ÿ“–
isResClassIIIcell.isResClassIII๐Ÿ“–
isPentagoncell.isPentagon๐Ÿ“–
getIcosahedronFacesโš ๏ธ Not yet available
maxFaceCountThis function exists for memory management and is not exposed.

Grid traversal functions

H3 C functionExample SwiftyH3 codeDocs
gridDistancetry originCell.gridDistance(to: destinationCell)๐Ÿ“–
gridRingtry cell.gridRing(distance: 1)๐Ÿ“–
gridRingUnsafeNot exposed. Use gridRing.
maxGridRingSizeThis function exists for memory management and is not exposed.
gridDisktry cell.gridDisk(distance: 2)๐Ÿ“–
maxGridDiskSizeThis function exists for memory management and is not exposed.
gridDiskDistancesNot exposed. Use try 1...3.map { cell.gridRing(distance: \$0) }.
gridDiskUnsafeNot exposed. Use gridDisk.
gridDiskDistancesUnsafeNot exposed. Use try 1...3.map { cell.gridRing(distance: \$0) }.
gridDiskDistancesSafeNot exposed. Use try 1...3.map { cell.gridRing(distance: \$0) }.
gridDisksUnsafeNot exposed. Use try cells.flatMap { cell in 1...3.flatMap { cell.gridRing(distance: \$0) } }.
gridPathCellstry cell1.path(to: ...)๐Ÿ“–
gridPathCellsSizeThis function exists for memory management and is not exposed.
cellToLocalIjโš ๏ธ Not yet available
localIjToCellโš ๏ธ Not yet available

Hierarchical grid functions

H3 C functionExample SwiftyH3 codeDocs
cellToParenttry cell.parent(at: .res1)๐Ÿ“–
cellToChildrentry cell.children(at: .res12)๐Ÿ“–
cellToChildrenSizetry cell.children(at: .res12).count๐Ÿ“–
cellToCenterChildtry cell.children(at: .res12).center๐Ÿ“–
cellToChildPostry parentCell.children(at: .res12).index(of: childCell)๐Ÿ“–
childPosToCelltry cell.children(at: .res12)[23]๐Ÿ“–
compactCellstry [cell1, ..., cell50].compacted๐Ÿ“–
uncompactCellstry [cell1, cell2, cell3].uncompacted(at: .res8)๐Ÿ“–
uncompactCellsSizeThis function exists for memory management and is not exposed.

Region functions

H3 C functionExample SwiftyH3 codeDocs
polygonToCellstry H3Polygon([...]).cells(at: .res7)๐Ÿ“–
maxPolygonToCellsSizeThis function exists for memory management and is not exposed.
polygonToCellsExperimentaltry H3Polygon([...]).cellsExperimental(at: .res7, containmentType: .overlapping)๐Ÿ“–
maxPolygonToCellsSizeExperimentalThis function exists for memory management and is not exposed.
cellsToLinkedMultiPolygontry [cell1, cell2, cell3].multiPolygon๐Ÿ“–
destroyLinkedMultiPolygonThis function exists for memory management and is not exposed.

Directed edge functions

H3 C functionExample SwiftyH3 codeDocs
areNeighborCellstry cell1.isNeighbor(of: cell2)๐Ÿ“–
cellsToDirectedEdgetry originCell.directedEdge(to: destinationCell)๐Ÿ“–
isValidDirectedEdgedirectedEdge.isValid๐Ÿ“–
getDirectedEdgeOrigintry directedEdge.origin๐Ÿ“–
getDirectedEdgeDestinationtry directedEdge.destination๐Ÿ“–
directedEdgeToCellsNot exposed. Use try (directedEdge.origin, directedEdge.destination).
originToDirectedEdgestry originCell.directedEdges๐Ÿ“–
directedEdgeToBoundarytry directedEdge.boundary๐Ÿ“–

Vertex functions

H3 C functionExample SwiftyH3 codeDocs
cellToVertextry cell.vertex(3)๐Ÿ“–
cellToVertexestry cell.vertices๐Ÿ“–
vertexToLatLngtry vertex.latLng๐Ÿ“–
isValidVertexvertex.isValid๐Ÿ“–

Miscellaneous H3 functions

H3 C functionExample SwiftyH3 codeDocs
degsToRadsNot exposed. Use Measurement<UnitAngle>(value: 23, unit: .degrees).converted(to: .radians).value.
radsToDegsNot exposed. Use Measurement<UnitAngle>(value: 1.2, unit: .radians).converted(to: .degrees).value.
getHexagonAreaAvgKm2H3Cell.Resolution.res8.averageHexagonArea.converted(to: .squareKilometers).value
getHexagonAreaAvgM2H3Cell.Resolution.res8.averageHexagonArea.value๐Ÿ“–
cellAreaRads2try cell.areaRads2๐Ÿ“–
cellAreaKm2try cell.area.converted(to: .squareKilometers).value
cellAreaM2try cell.area.converted(to: .squareMeters).value๐Ÿ“–
getHexagonEdgeLengthAvgKmH3Cell.Resolution.res8.averageHexagonEdgeLength.converted(to: .kilometers).value
getHexagonEdgeLengthAvgMH3Cell.Resolution.res8.averageHexagonEdgeLength.value๐Ÿ“–
edgeLengthKmtry directedEdge.length.converted(to: .kilometers).value
edgeLengthMtry directedEdge.length.value๐Ÿ“–
edgeLengthRadstry directedEdge.lengthRads.value๐Ÿ“–
getNumCellsH3Cell.Resolution.res3.numberOfCells๐Ÿ“–
getRes0CellsH3Cell.res0Cells๐Ÿ“–
res0CellCountThis function exists for memory management and is not exposed.
getPentagonsH3Cell.Resolution.res3.pentagons๐Ÿ“–
pentagonCountThis function exists for memory management and is not exposed.
greatCircleDistanceKmh3LatLng1.distance(to: h3LatLng2).converted(to: .kilometers).value
greatCircleDistanceMh3LatLng1.distance(to: h3LatLng2).value๐Ÿ“–
greatCircleDistanceRadsh3LatLng1.distanceRads(to: h3LatLng2).value๐Ÿ“–
describeH3Errordo {...} catch { print(error.errorDescription) }๐Ÿ“–

Note

The Measurement<UnitType> types and LocalizedError protocol, including related methods and properties, are part of Foundation. Include import Foundation to use them.

Core Location and MapKit support

CLLocationCoordinate2D

You can convert an H3LatLng value to CLLocationCoordinate2D and vice versa using initializers or computed properties.

// H3LatLng โžก๏ธ CLLocationCoordinate2D
let coordinateFromProperty: CLLocationCoordinate2D = H3LatLng(latitudeDegs: 37.7955, longitudeDegs: -122.3937).coordinates
let coordinateFromInitializer = CLLocationCoordinate2D(H3LatLng(latitudeDegs: 37.7955, longitudeDegs: -122.3937))

// CLLocationCoordinate2D โžก๏ธ H3LatLng
let h3LatLngFromProperty: H3LatLng = CLLocationCoordinate2D(latitude: 37.7955, longitude: -122.3937).h3LatLng
let h3LatLngFromInitializer = H3LatLng(CLLocationCoordinate2D(latitude: 37.7955, longitude: -122.3937))

MKPolygon and MKMultiPolygon

You can create an MKPolygon with an initializer taking [H3LatLng] or H3Polygon values. Analogically, you can initialize MKMultiPolygon with [H3Polygon] array.

// H3 with MapKit for SwiftUI example

import SwiftUI
import MapKit
import SwiftyH3

struct H3CellMapExampleView: View {
    let cellBoundary = try! H3LatLng(latitudeDegs: 37.7955, longitudeDegs: -122.3937).cell(at: .res4).boundary
    
    var body: some View {
        Map {
            MapPolygon(MKPolygon(cellBoundary))
        }
    }
}

MapContent (MapKit for SwiftUI)

H3Cell, H3Polygon, and H3DirectedEdge conform to the MapContent protocol which means that you can use them as map content when using MapKit for SwiftUI.

// H3 with MapKit for SwiftUI example

import SwiftUI
import MapKit
import SwiftyH3

struct H3CellMapExampleView: View {
    var body: some View {
        Map {
            H3Cell("87283082affffff")
            H3DirectedEdge("115283473fffffff").stroke(.blue, lineWidth: 2)
            try? ["8528342ffffffff", "85283093fffffff"].map { H3Cell(\$0)! }.multiPolygon[0]
        }
    }
}

License