DEV Community

Samuel Edwin
Samuel Edwin

Posted on

Change variable values instantly without rebuilds

Most of the apps distributed in the App Store requires a back end server. Facebook, Instagram, Twitter, Netflix, Amazon, you name it.

There are at least two kinds of servers involved when building these apps: production server and testing server.
Testing server is used to prevent unstable features from going to production.

This practice impacts our development activities. We often need to switch servers depending on the situation. How do we handle changing these servers?

The simple way and the complexities it introduced

let productionURL = "https://api.myapp.com"
let stagingURL = "https://staging-api.myapp.com"

let baseURL = productionURL
Enter fullscreen mode Exit fullscreen mode

This is the typical way people do to switch servers, simple and straightforward.
Change the baseURL to either productionURL or stagingURL when you need to, rebuild the app, and see the results.

While this approach works, there are some problems you need to be aware of:

1. It gets slower over time

Your project's build speed will get slower as your codebase grows.
I have reached a point where I have to wait for 3 minutes just to change servers.
People slacking off waiting for their code to compile

2. Human error eventually hits hard

When using the above technique, you have to modify your code in order to switch servers.

- let baseURL = productionURL
+ // let baseURL = productionURL
+ let baseURL = stagingURL
Enter fullscreen mode Exit fullscreen mode

You have to be very careful to not let the code above get committed and published to the App Store.

This of course can be prevented by code review, but humans eventually make mistakes. It is only a matter of time when you let your guard down and published this to production. I did, at some point in my career.

3. Huge inconvenience for testers

Aside from developers, testers are the ones that also need access to both staging and production servers.

If you use CI/CD system to distribute test apps, then you need to provide two builds with each build pointing to a different server.

This is a big waste of time. Builds take twice longer, and also testers need to download the builds again just to switch servers.

So now you're convinced that even though the simple technique works, it has some drawbacks.
Wouldn't it be nice if we can switch servers instantly?


SwiftTweaks to the rescue

SwiftTweaks is a library to change things instantly without having to recompile, and written in ... Swift. I thought it was PHP 😮.

How does it work?

SwiftTweaks works by showing a pop up when you shake your phone. Choose whatever settings you want to tweak and that's it.

In our case, SwiftTweaks will show a menu so we can switch between servers instantly. No rebuilds needed.
A video showing how to use SwiftTweaks from the app

If this looks appealing to you, then let me show you how it's done.

Let's build our own tweaks

Create a new project and add the library as instructed here.
I won't go into details here since this is not a beginner article.
After you're done, we can start the next steps.

1. Create a tweak store

// AppTweaks.swift
import SwiftTweaks

struct AppTweaks: TweakLibraryType {
    // A
    static let serverURL = Tweak<StringOption>(
        "General",
        "Networking",
        "Server URL",
        options: [
            "https://api.myapp.com", 
            "https://api-staging.myapp.com"
        ]
    )

    static var defaultStore: TweakStore {
        return TweakStore(
            tweaks: [serverURL], // B
            enabled: TweakDebug.isActive
        )
    }
}
Enter fullscreen mode Exit fullscreen mode

This seems like a lot of code but trust me it is simpler than what it looks like.

There are two things that we do here, as marked in comments A and B.

In comment A, we are creating a tweakable serverURL with two available options: https://api.myapp.com, https://api-staging.myapp.com.
The first option will be chosen as the default.
This option will show up under the General > Networking > Server URL option.

In comment B, we are putting all the available options in the tweaks argument so they can show up in the UI.

2. Change the default UIWindow

These options will show up when you shake the phone while the app is active.
In order to do that, we need to use the TweakWindow class provided by SwiftTweaks instead of UIWindow.

window = TweakWindow(
    frame: UIScreen.main.bounds, 
    tweakStore: AppTweaks.defaultStore
)

// Create the root view controller as usual
window?.rootViewController = MyViewController()
window?.makeKeyAndVisible()
Enter fullscreen mode Exit fullscreen mode

3. Use the chosen option from the code

Now we need to change how the baseURL gets its value.

- let baseURL = productionURL
+ let baseURL = AppTweaks.assign(AppTweaks.serverURL).value
Enter fullscreen mode Exit fullscreen mode

Instead of hardcoding the server URLs, we can now just let SwiftTweaks decide which server URL that we want to use.

4. Restart the app and see the changes

We'll now see how easy it is to change configurations using SwiftTweaks:

  • Run your app as usual
  • Shake your device (ctrl + cmd + z from the simulator), a view controller will pop up showing all your configurations.
  • Change your selected server from production to staging.
  • Restart your app to see the changes.

A video showing how to use SwiftTweaks from the app

That's it! No more code changes needed when you want to switch servers. You can switch servers whenever you like.

I don't want my users to use this tool

Me too. God knows what weird things your users will do with this.

So how do you prevent this tool from leaking to app store builds? nothing.

Yes, you don't have to do anything. SwiftTweaks is smart enough to know that this will only show up in debug builds.


Other useful SwiftTweaks usages

Now you have seen how powerful this tool is. You might be wondering, what else can you use this for? I have some ideas for you.

Toggle onboardings or tutorials

Onboardings or tutorials teach users on how to use your app. It is a very common pattern nowadays.

The thing with onboardings is they only show up once when the users open the app for the first time.

let showOnboarding = !UserDefaults
    .standard
    .bool(forKey: "has_shown_onboarding")

if showOnboarding {
    UserDefaults
        .standard.set(true, forKey: "has_shown_onboarding")

    window?.rootViewController = OnboardingViewController()
} else {
    window?.rootViewController = MainViewController()
}
Enter fullscreen mode Exit fullscreen mode

Ordinary humans like me can't develop onboardings perfectly on the first try. We have to run the app multiple times until we got it right.
I usually hard coded showOnboarding to true until I've finished with the development.

Thanks to SwiftTweaks, I don't have to do any hard coding anymore. All I have to do is create a new tweak.

static let showOnboarding = Tweak(
    "General",
    "Onboarding",
    "Show onboarding",
    !UserDefaults.standard.bool(forKey: "has_shown_onboarding")
)
Enter fullscreen mode Exit fullscreen mode

And then I just need to change the logic for a bit.

- let showOnboarding = !UserDefaults
-     .standard
-     .bool(forKey: "has_shown_onboarding")
+ let showOnboarding = 
+    AppTweaks.assign(AppTweaks.alwaysShowOnboarding)

Enter fullscreen mode Exit fullscreen mode

Toggle SDK loggings

Third party SDKs such as Mixpanel have logging capability to ease debugging.

Mixpanel.mainInstance().loggingEnabled = true
Enter fullscreen mode Exit fullscreen mode

You mostly want this option to be turned off unless for some occasions. The reason is the logs can pollute your debugging console and make important information harder to find.

SwiftTweaks lets you toggle this on/off anytime you want.

static let enableMixpanelLogging = Tweak(
    "General",
    "Logging",
    "Enable Mixpanel logging",
    false
)

Mixpanel.mainInstance().loggingEnabled = 
    AppTweaks.assign(AppTweaks.enableMixpanelLogging)
Enter fullscreen mode Exit fullscreen mode

Conclusion

We do some small tweaks here and there in our coding activity. Tweaking those configurations doesn't have to be time consuming. SwiftTweaks lets you do small tweaks instantly. This will save you a lot of time.

There are so many things that you can do with this. You can change colors, fonts, animations on the fly with out having to recompile your code.

Start using it now see how your quality of life gets better because of it.

Discussion (0)