0

This is not a duplicate question. Current "answers" to this problem use Objective-C, which allows for more expanded #Define statements. The existing suggested solutions result in an IP address directly changing within a file; a build artifact I was trying to avoid.

I'm currently building some tests for a mobile app, built in Xcode with swift. This app uses a cloud service to get status of items, and store/retrieve login information.

----------      ---------
| Server | ---> | Cloud | 
----------      ---------

When testing, however, I use a dummy server running on nodeJS to provide the expected responses, so I don't have to, say, register an account every time I want my UI tests to check the registration process.

----------      ---------
| Server | ---X | Cloud | 
----------      ---------
     |         ----------
      -------> | nodeJS |
               ----------

In order for this to work well on iOS simulator as well as on an external device, I need to specify the IP of the nodeJS server. I have been doing this manually, but I wanted to make it do so automatically.

Here's the rub: I want to be able to do this at runtime, or at least at buildtime without artifacts.

Solutions I've attempted:

  1. PList Variables
    I've created a variable in my info.plist called TestServerIP. I then use a bash script at buildtime to change the value of the variable to my en0 address:

    #!/bin/bash
    localUrl=$(ipconfig getifaddr en0)
    plutil -replace TestServerIP -string \"$localUrl\" $SRCROOT/gdocntl/Info.plist
    

    The problem with this is that I now have an IP address hardcoded in my .plist file.

  2. New plist file
    I wanted to simply make a new plist file with only the IP var with bash, but you cannot create files outside of xcode and add them to the bundle easily. I started looking into this, but quickly found I'd be trying to do XML search/replacing... and we all know how well that works.

  3. Swift script
    I then tried using a modified swift script to pull the IP at runtime, from https://stackoverflow.com/a/25627545/9952260. The problem here is that when running on a physical iOS device, this grabs the IP of the iDevice, not the machine.

I've been trying to implement a variation of (1), where I instead define TestServerIP to be something like ${NODE_JS_IP}, but I'm not sure how I can define this using Xcode. I've been down a few rabbit holes:

TL;DR: How can I define the value of a custom swift flag or compiler variable, something I can assign to a variable in a plist, at build time with a bash script?

Quentin
  • 1
  • 4
  • If I understand your goal, you should be able to combine the `${NODE_JS_IP}` idea with option 1 to make this work. Within the Xcode build settings, add a user-defined setting called `NODE_JS_IP` with the address as its value. Then add a build phase that uses the macro expansion for plist variable replacement. – Phillip Mills Feb 07 '19 at 19:24
  • @PhillipMills my question is what the mechanics of setting NODE_JS_IP with the address would be. An `export` statement, or something? – Quentin Feb 07 '19 at 19:55
  • Go to Xcode's build settings for your target. Click on a `+` sign near the top middle of the screen. Select "Add User-defined Setting". – Phillip Mills Feb 07 '19 at 22:30
  • I don't think I'm being clear: I understand how to create a user defined setting. My question is; how would I put the *address* (that is, the *value* of the setting) in? Are you suggesting I manually change it every time my IP changes? – Quentin Feb 08 '19 at 01:46
  • I do what you described in #2. Make 1 plist with the prod credentials that only gets compiled into the main app target and a separate one with the same name that gets compiled into the test target. You can use plist buddy to modify the test target plist https://www.willowtreeapps.com/ideas/using-plistbuddy-to-inject-app-secrets-and-keys-at-build-time – pixelrevision Feb 12 '19 at 20:51
  • @pixelrevision Its a good idea but still runs into the problem I had with #2, and the article linked states it: "Note that this does not fully protect app keys and secrets." In my case, that's an IP. – Quentin Feb 22 '19 at 21:35

0 Answers0