{"id":18871357,"url":"https://github.com/sfomuseum/swift-mbtiles","last_synced_at":"2026-03-07T09:04:31.800Z","repository":{"id":102139189,"uuid":"313423857","full_name":"sfomuseum/swift-mbtiles","owner":"sfomuseum","description":"Swift package for reading and caching data from MBTile databases.","archived":false,"fork":false,"pushed_at":"2024-10-01T20:07:46.000Z","size":940,"stargazers_count":2,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-01T11:13:40.705Z","etag":null,"topics":["mbtiles","sqlite","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sfomuseum.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-11-16T20:51:00.000Z","updated_at":"2024-11-28T20:51:08.000Z","dependencies_parsed_at":null,"dependency_job_id":"6619a486-bc2c-44b9-a772-cc1b2a4189fd","html_url":"https://github.com/sfomuseum/swift-mbtiles","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/sfomuseum/swift-mbtiles","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfomuseum%2Fswift-mbtiles","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfomuseum%2Fswift-mbtiles/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfomuseum%2Fswift-mbtiles/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfomuseum%2Fswift-mbtiles/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sfomuseum","download_url":"https://codeload.github.com/sfomuseum/swift-mbtiles/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sfomuseum%2Fswift-mbtiles/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30210385,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T09:02:10.694Z","status":"ssl_error","status_checked_at":"2026-03-07T09:02:08.429Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mbtiles","sqlite","swift"],"created_at":"2024-11-08T05:25:35.282Z","updated_at":"2026-03-07T09:04:31.770Z","avatar_url":"https://github.com/sfomuseum.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# swift-mbtiles\n\nSwift package for reading and caching data from MBTile databases.\n\n## Important\n\nWork in progress, including documentation.\n\n## Example\n\n```\n// Logger is part of the swift-log packacge and is an optional parameter for\n// the swift-mbtiles classes described below\n\nlet logger = Logger(label: \"org.example.mbtiles\")\nlogger.logLevel = .info\n\nlet tiles_resolver = TileResolver()\n\nlet root = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!\nlet tiles_collection = MBTilesCollection(root: root, logger: logger)\n        \nlet tiles_pool = MBTilesDatabasePool(logger: logger)\nlet tiles_reader = MBTilesReader(resolver: tiles_resolver, logger: logger)\nlet tiles_cache = MBTilesCache(db_pool: tiles_pool, db_reader: tiles_reader, resolver: tiles_resolver, throttle: 10, logger: logger)\n```\n\nAn attempt has been made to create small and discrete classes that only do a finite set of tasks. They are:\n\n* `MBTilesCollection` This class manages a set of MBTiles database contained in a parent directory.\n* `MBTilesDatabasePool` This class manages database connections to one or more MBTiles (SQLite) databases.\n* `MBTilesReader` This class manages queries of and reading data from an MBTiles (SQLite) database.\n* `MBTilesCache` This class manages a caching layer for tile requests. Interface-wise it's a bit of a mess; this is discussed more below.\n\nSome of these classes suffer, in a technical sense, from \"leaky abstractions\". That's not ideal but in the interest of \"getting things done\" they are understood as acceptable compromises until such a time as they are not.\n\nUnder the hood this package is using [stephencelis/SQLite.swift](https://github.com/stephencelis/SQLite.swift) for database access. The (SQLite) database layer has not been abstracted behind a single class (`MBTilesDatabasePool`). The different `swift-mbtiles` classes pass each other `SQLite` instances. This is one of those places where, in time, we might be able to develop a higer level abstraction for MBTiles-related tasks but, as of this writing, it's still too soon for that.\n\nThere is also [a branch that uses FMDB](https://github.com/sfomuseum/swift-mbtiles/tree/fmdb) but it contains a crashing bug that I haven't been able to debug (taking in to account all the things that the documentation says to do).\n\nDid you notice the instatiation of the `TileResolver()` class above? This is code that you will need to implement and that conforms to the `MBTilesResolver` protocol below. This is code used to resolve a URL in to MBTile database specifics like the name of the database and Z, X, Y coordinates.\n\nOnce all of these classes have been instantiated you can precache the tiles in your MBTiles databases like this:\n\n```\nDispatchQueue.global(qos: .background).async {\n                \n\tlet db_rsp = tiles_collection.Databases()\n\tvar database_urls = Array\u003cURL\u003e()\n                \n\tswitch db_rsp {\n\tcase .failure(let error):\n\t\t// handle error here\n\tcase .success(let urls):\n\t\tdatabase_urls = urls\n\t}\n                \n\tlet cache_rsp = tiles_cache.PrecacheTileData(databases: database_urls)\n                \n\tif case .failure(let error) = cache_rsp {\n\t\t// handle error here\n\t}\n}\t\n```\n\nAnd then later on in your code when a tile is requested we check to see if we have a cached version:\n\n```\nif let _ = tiles_cache.missing.object(forKey: tile_path as NSString) {\n\treturn .failure(Errors.missingTileError)\n}\n\t\t\nif let tile_data = tiles_cache.cache.object(forKey: tile_path as NSString) {\n\treturn .success(tile_data as String)\n}\n```\n\nSee the way we're calling `tiles_cache.missing.object` and `tiles_cache.cache.object` ? These are not ideal interfaces for dealing with tile caching. What's really needed is an interface for _tiles_ that sits on top of a generic interface for caching and there hasn't been the luxury of time to figure that out yet. It is definitely an area for improvement.\n\nAssuming there isn't a cached version (and we don't know that the tile is missing) the tile data would be retrieved like this:\n\n```\nlet tile_path = \"tiles/example/10/12/345.png\"\n\nvar tile: MBTile\n\t\t\t\nlet tile_rsp = tiles_resolver.MBTileFromPath(path: tile_path)\n\t\t\t\nswitch tile_rsp {\ncase .failure(let error):\n\t// handle error here\ncase .success(let t):\n\ttile = t\n}\n\t\t\t\nlet db_path = tiles_collection.DatabasePathFromTile(tile: tile)\n\t\t\t\nlet data_rsp = tiles_reader.ReadTileAsDataURL(db_pool: tiles_pool, db_path: db_path, tile: tile)\n\t\t\t\nswitch data_rsp {\ncase .failure(let error):\n\t// handle error here\t\t\t\t\ncase .success(let tile_data):\n\ttiles_cache.cache.setObject(NSString(string: tile_data), forKey:NSString(string: tile_path))\n\t// do something with tile data here\n}\n```\n\n\n## MBTilesResolver\n\n```\npublic protocol MBTilesResolver {\n    func PrefixFromPath(path: String) -\u003e Result\u003cString, Error\u003e\n    func MBTileFromPath(path: String) -\u003e Result\u003cMBTile, Error\u003e\n    func PathFromMBTile(tile: MBTile) -\u003e Result\u003cString, Error\u003e\n}\n```\n\n## See also\n\n* https://github.com/stephencelis/SQLite.swift","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsfomuseum%2Fswift-mbtiles","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsfomuseum%2Fswift-mbtiles","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsfomuseum%2Fswift-mbtiles/lists"}