1

My mobile app has quite a lot of hard-coded data, that I want to share between the native Android and iOS versions of the app. I don't want to create two settings files for each app: I would like to have a single place where the information is stored.

My first thought was using a JSON file embedded with my app and decode it at runtime.

Instead my goal here is to deserialize the app's data at compile time, in order to:

  • track potential errors within the JSON file or the decoding code before shipping the app: the build will fail instead
  • avoid being slowed down by some deserialization at startup time
  • avoid leaving unencrypted app data lying around as JSON files (.ipa/.apk are zip files where resources can be easily extracted), I'd rather have it obfuscated in code

I'm looking for a command line tool that I could add to my build scripts that given a JSON file infer a schema and thus classes AND instantiates an object with all the app settings.

For instance given the following settings.json file:

{
    "gravity": 9.81,
    "scientists": ["Kepler", "Einstein", "Newton"],
    "planets": [
        {
            "name": "Mars",
            "radius": 3390
        },
        {
            "name": "Venus",
            "radius": 6052
        }
    ]
}

I would like to generate automatically a Settings.swift file that could look like:

struct Settings {

    struct Planet {
        var name: String
        var radius: Int
    }

    var gravity: Double
    var scientists: [String]
    var planets: [Planet]

    static func content() -> Settings {
        return Settings(gravity: 9.81, scientists: ["Kepler", "Einstein", "Newton"], planets: [Planet(name: "Mars", radius: 3390), Planet(name: "Venus", radius: 6052)])
    }
}

I could then include the generated file into my project and call Settings.content() once, keep it in a global variable and use it throughout my project.

I want to achieve the same with Android as well.

Tools like quicktype or json2swift do half the job and don't generate the object instantiation bit, that still needs to be done at runtime.

Any idea?

chrisben
  • 955
  • 8
  • 16
  • The settings I'm talking about are not user defaults, but app defaults. The app will be shipped with these settings and they won't change. I should call them "app data" instead of settings if that's clearer. – chrisben Sep 20 '18 at 09:11

2 Answers2

0

I have created an open source NodeJS mobile_app_data tool to achieve what I wanted.

chrisben
  • 955
  • 8
  • 16
-1

A possible solution will be as follows:

  1. Save the .json file in the project directory
  2. In AppDelegate applicationDidFinishLauncing() read the above file into a Data object (Read JSON file with Swift 3)
  3. Make your Settings class implement Decodable (your inner class Planet will need to implement Decodable as well)
  4. Call JsonDecoder().decode() and provide the data you obtained in 2)
  5. You can then save this value anywhere you want

I just noticed that you needed the generation to happed when Settings.content() is called. Follow the above steps just move step 2) into the content() function

jms
  • 747
  • 6
  • 19
  • Your suggestion is an answer to: "My first thought was using a JSON file embedded with my app and decode it at runtime." This I know how to do. That's not my goal, for the reasons explained above. – chrisben Sep 20 '18 at 10:22
  • 1
    I see. Can you look at the following tool https://github.com/SwiftGen/SwiftGen. It feels like it will help you closer to the solution – jms Sep 20 '18 at 10:31