I want to develop an iOS application that displays Open Street Map offline

51 views Asked by At

I want to develop an application that displays Open Street Map offline. I save an Open Street map tile in the following way:

class HomeViewController: UIViewController, GMSMapViewDelegate, CLLocationManagerDelegate, DistanceCalculationDelegate{
    func startMonitoringNetwork() {
        if let currentLatString = UserDefaults.standard.string(forKey: "myLat"),
           let currentLonString = UserDefaults.standard.string(forKey: "myLon"),
           let currentLat = Double(currentLatString),
           let currentLon = Double(currentLonString) {
            let zoomLevel = 15
            let centerTileCoords = tileCoordinates(fromLatitude: currentLat, longitude: currentLon, zoomLevel: zoomLevel)
            
            let range = 4  
            for dx in -range...range {
                for dy in -range...range {
                    let tileX = centerTileCoords.x + dx
                    let tileY = centerTileCoords.y + dy
                    downloadTile(zoom: zoomLevel, x: tileX, y: tileY)
                }
            }
        }
    }

    func downloadTile(zoom: Int, x: Int, y: Int) {
        let urlString = "https://tile.openstreetmap.org/\(zoom)/\(x)/\(y).png"
        guard let url = URL(string: urlString) else { return }
        print(url)
        let task = URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else { return }
            
            self.saveTileData(data, zoom: zoom, x: x, y: y)
        }
        
        task.resume()
    }
    
    func saveTileData(_ data: Data, zoom: Int, x: Int, y: Int) {
        let fileManager = FileManager.default
        guard let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else { return }

        
        let zoomDir = documentsDirectory.appendingPathComponent("tiles/\(zoom)")
        let xDir = zoomDir.appendingPathComponent("\(x)")

      
        if !fileManager.fileExists(atPath: xDir.path) {
            try? fileManager.createDirectory(at: xDir, withIntermediateDirectories: true)
        }

        let tileFilePath = xDir.appendingPathComponent("\(y).png")
        do {
            try data.write(to: tileFilePath)
            print("Tile saved: \(tileFilePath.path)")
        } catch {
            print("Error saving tile: \(error)")
        }
    }
}

The following data are saved in this way.

  • file:///var/mobile/Containers/Data/Application/2316925A-8954-4407-A286-AF81F862F2D2/Documents/tiles/15/29096/12903.png
  • file:///var/mobile/Containers/Data/Application/2316925A-8954-4407-A286-AF81F862F2D2/Documents/tiles/15/29096/12903.png
  • file:///var/mobile/Containers/Data/Application/2316925A-8954-4407-A286-AF81F862F2D2/Documents/tiles/15/29096/12903.png
  • file:///var/mobile/Containers/Data/Application/2316925A-8954-4407-A286-AF81F862F2D2/Documents/tiles/15/29096/12903.png

But the data taken out are these with the next code:

class OpenStreetMapController: UIViewController, MKMapViewDelegate {
    @IBOutlet weak var openStreetMap: MKMapView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let overlay = CustomTileOverlay(urlTemplate: nil)
        let tilePath = MKTileOverlayPath(x: 35, y: 139, z: 17, contentScaleFactor: 1.0)
        overlay.loadTile(at: tilePath) { (data, error) in
        }
        overlay.canReplaceMapContent = true
        openStreetMap.addOverlay(overlay)
        openStreetMap.delegate = self
    }
    
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        if let tileOverlay = overlay as? MKTileOverlay {
            let renderer = MKTileOverlayRenderer(tileOverlay: tileOverlay)
            return renderer
        }
        return MKOverlayRenderer()
    }
    
    class CustomTileOverlay: MKTileOverlay {
        
        override func loadTile(at path: MKTileOverlayPath, result: @escaping (Data?, Error?) -> Void) {
            let fileManager = FileManager.default
            guard let documentsDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first else {
                result(nil, NSError(domain: "TileErrorDomain", code: 0, userInfo: nil))
                return
            }

            let tileFilePath = documentsDirectory
                                .appendingPathComponent("tiles/\(path.z)")
                                .appendingPathComponent("\(path.x)")
                                .appendingPathComponent("\(path.y).png")
            print(tileFilePath)

            if let tileData = try? Data(contentsOf: tileFilePath) {
                result(tileData, nil)
            } else {
                result(nil, NSError(domain: "TileErrorDomain", code: 1, userInfo: nil))
            }
        }
  • file:///var/mobile/Containers/Data/Application/7C2AB696-8425-4DA7-A2AA-0856C4B4C677/Documents/tiles/17/35/139.png
  • file:///var/mobile/Containers/Data/Application/7C2AB696-8425-4DA7-A2AA-0856C4B4C677/Documents/tiles/6/54/24.png
  • file:///var/mobile/Containers/Data/Application/7C2AB696-8425-4DA7-A2AA-0856C4B4C677/Documents/tiles/6/57/26.png
  • file:///var/mobile/Containers/Data/Application/7C2AB696-8425-4DA7-A2AA-0856C4B4C677/Documents/tiles/6/57/20.png

Please tell me the cause.

I develop these code with ChatGPT but it is not correct. I don`t know how to solve this problem.

0

There are 0 answers