Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blank maps when using local mbtiles with local style on iOS #1366

Closed
prawel opened this issue Jul 13, 2023 · 6 comments
Closed

Blank maps when using local mbtiles with local style on iOS #1366

prawel opened this issue Jul 13, 2023 · 6 comments
Labels
bug Something isn't working iOS

Comments

@prawel
Copy link

prawel commented Jul 13, 2023

Describe the bug

I'm playing with MapLibre native library for ios and I get non-working behaviour. When I try using local mbtiles on iOS simulator, I get blank maps. Compass is visible, scale is visible, but the actual map contents are not.

The tiles I'm using were downloaded from https://data.maptiler.com/downloads/tileset/osm/europe/poland/, but it doesn't matter which one I try.

MapView.swift:

import Mapbox
import MapKit
import SwiftUI

struct MapView: UIViewRepresentable {
    func makeUIView(context: Context) -> MGLMapView {
        let styleURL = URL(string: "file:///Users/pk/Documents/Projekty/piotr/offlinemaps/styles/osmbright.json");

        let mapView = MGLMapView(frame: .zero, styleURL: styleURL);

        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight];
        mapView.showsUserLocation = true;
        mapView.showsScale = true;
        mapView.showsHeading = true;
        mapView.compassView.compassVisibility = .visible;
        mapView.debugMask = [.tileBoundariesMask, .tileInfoMask, .timestampsMask];
        mapView.setCenter(
            CLLocationCoordinate2D(latitude: 52.237049, longitude: 21.017532),
            zoomLevel: 12,
            animated: false);
        
        mapView.delegate = context.coordinator;
        
        return mapView;
    }
    
    func updateUIView(_ uiView: MGLMapView, context: Context) {}
    
    func makeCoordinator() -> MapView.Coordinator {
        Coordinator(self)
    }
    
    final class Coordinator: NSObject, MGLMapViewDelegate {
        var control: MapView
        
        init(_ control: MapView) {
            self.control = control
        }

        func mapViewDidFinishLoadingMap(_ mapView: MGLMapView) {
            // write your custom code which will be executed
            // after map has been loaded
            print("mapViewDidFinishLoadingMap");
        }
        
        func mapViewWillStartLoadingMap(_ mapView: MGLMapView) {
            print("will start loading")
        }

        func mapViewWillStartRenderingMap(_ mapView: MGLMapView) {
            print("will start rendering")
        }

        func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) {

        }
        
        func mapViewDidFinishRenderingMap(_ mapView: MGLMapView, fullyRendered: Bool) {
            print("did finish rendering")
        }
        
        func mapViewDidBecomeIdle(_ mapView: MGLMapView) {

        }
        
        func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
            return nil
        }
         
        func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
            return true
        }
    }
}

struct MapView_Previews: PreviewProvider {
    static var previews: some View {
        MapView()
    }
}

osmbright.json:

{
  "version": 8,
  "name": "OSM Bright",
  "metadata": {
    "mapbox:type": "template",
    "mapbox:groups": {
      "1444849364238.8171": {
        "collapsed": false,
        "name": "Buildings"
      },
      "1444849354174.1904": {
        "collapsed": true,
        "name": "Tunnels"
      },
      "1444849388993.3071": {
        "collapsed": false,
        "name": "Land"
      },
      "1444849242106.713": {
        "collapsed": false,
        "name": "Places"
      },
      "1444849382550.77": {
        "collapsed": false,
        "name": "Water"
      },
      "1444849345966.4436": {
        "collapsed": false,
        "name": "Roads"
      },
      "1444849334699.1902": {
        "collapsed": true,
        "name": "Bridges"
      }
    }
  },
  "zoom": 12,
  "bearing": 0,
  "pitch": 0,
  "sources": {
    "openmaptiles": {
      "type": "vector",
      "url": "mbtiles:///Users/pk/Documents/Projekty/piotr/offlinemaps/tiles/maptilerpoland.mbtiles"
    }
  },
  "sprite": "file:///Users/pk/Documents/Projekty/piotr/offlinemaps/sprites/basic-v8",
  "glyphs": "file:///Users/pk/Documents/Projekty/piotr/offlinemaps/glyphs/{fontstack}/{range}.pbf",
  "layers": [
    {
      "id": "background",
      "type": "background",
      "paint": {
        "background-color": "#f8f4f0"
      }
    },
    {
      "id": "landcover-glacier",
      "type": "fill",
      "metadata": {
        "mapbox:group": "1444849388993.3071"
      },
      "source": "openmaptiles",
      "source-layer": "landcover",
      "filter": [
        "==",
        "subclass",
        "glacier"
      ],
      "layout": {
        "visibility": "visible"
      },
      "paint": {
        "fill-color": "#fff",
        "fill-opacity": {
          "base": 1,
          "stops": [
            [
              0,
              0.9
            ],
            [
              10,
              0.3
            ]
          ]
        }
      }
    },
    (......)
  ]
}

In debug panel in Xcode there is one message only: "will start rendering" which comes from this function:

func mapViewWillStartRenderingMap(_ mapView: MGLMapView) {
    print("will start rendering")
}

I have not entered any key, because I'm using local files only.
Files are accessible from ios simulator, I've checked that.

Platform information

  • OS: MacOS
  • Platform iOS
  • Version 5.13.0
@prawel prawel added the bug Something isn't working label Jul 13, 2023
@louwers
Copy link
Collaborator

louwers commented Jul 13, 2023

Stupid iOS question, but can the iOS simulator read from the local file system?

@ntadej
Copy link
Collaborator

ntadej commented Jul 13, 2023

Afaik no

@prawel
Copy link
Author

prawel commented Jul 13, 2023

it can, it does read and print the contents of the files. Checked already

@louwers
Copy link
Collaborator

louwers commented Jul 13, 2023

@prawel Yes you are right, since the style is definitely loaded from the local filesystem.

I am not sure if the style syntax of the source is correct. See this comment:

#17 (comment)

Definitely needs to be better documented.

@prawel
Copy link
Author

prawel commented Jul 13, 2023

unfortunately, this is not the case, it didn't change much.
But I know that the paths are correct, and this has to be something with loading itself, because when the path to mbtiles is wrong, other coordinator events fire

@louwers louwers added the iOS label Jul 13, 2023
@polvi
Copy link
Collaborator

polvi commented Jul 24, 2023

Here is my attempt that appears to work. Very hackey and would love any suggestions to improve. style.json and APT_BASE.mbtiles are bundled with the app. Definitely open to suggestions but this does work for me. Essentially it is grabbing the mbtiles location and runtime, and rewriting the style.json with that value.

struct MapView: UIViewRepresentable {
    func makeUIView(context: Context) -> MGLMapView {
        let mapView = MGLMapView(frame: .zero)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        mapView.delegate = context.coordinator
        
        
        guard let localMbtiles = Bundle.main.url(forResource: "APT_BASE", withExtension: "mbtiles") else {
            fatalError("Failed to find the style file.")
        }
        
        guard let styleURL = Bundle.main.url(forResource: "style", withExtension: "json") else {
            fatalError("Failed to find the style file.")
        }
        
        // Load the style.json template from your bundle
        if let path = Bundle.main.path(forResource: "style", ofType: "json") {
            do {
                var styleJSON = try String(contentsOfFile: path, encoding: .utf8)
                
                // let localMbString = localMb.absoluteString
                styleJSON = styleJSON.replacingOccurrences(of: "{{LOCAL_FILE_NAME}}", with: localMbtiles.path)
                let temporaryDirectory = FileManager.default.temporaryDirectory
                let temporaryFileURL = temporaryDirectory.appendingPathComponent("temp_style.json")
                try styleJSON.write(to: temporaryFileURL, atomically: true, encoding: .utf8)
                
                // Set the temporary file's URL as the mapView.styleURL
                mapView.styleURL = temporaryFileURL
                
                
            } catch {
                print("Error loading style.json template: \(error)")
            }
        }
...

Style.json section:

    "sources": {
        "local_data": {
              "type": "vector",
              "tiles": ["mbtiles://{{LOCAL_FILE_NAME}}"]
        },
...

@maplibre maplibre locked and limited conversation to collaborators Jul 24, 2023
@louwers louwers converted this issue into discussion #1411 Jul 24, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
bug Something isn't working iOS
Projects
None yet
Development

No branches or pull requests

4 participants