Disable Print Statements for Production Releases in Xcode

Disable Print Statements for Production Releases in Xcode

With just a couple configuration changes and a bit of code you can disable print statements in your production apps using Xcode.

Go to the profile of  Jonathan Banks
Jonathan Banks
3 min read

Imagine writing an iOS application that's dealing with sensitive information; credit card numbers, passwords, social security numbers, or other personally identifiable and sensitive information.  The time-tested and reliable print statement is used to log data while writing and debugging the app.

Those print statements should not be visible in the production version of that application. Bad actors with jailbroken iOS devices have access to the binary and then gain insights into how the app operates from these print statements.  How do developers prevent this?

The solution is a matter of a bit of Xcode configuration and a splash of code.

Xcode Setup and Print Method

First, override the Swift print statement and apply a logical decision to print based on the current mode that Xcode is in, either production or test.

Add the following code at a global level in the Xcode project:

func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
    
    #if DEBUG
    
    var idx = items.startIndex
    let endIdx = items.endIndex
    
    repeat {
        Swift.print(items[idx], separator: separator, terminator: idx == (endIdx - 1) ? terminator : separator)
        idx += 1
    }while idx < endIdx
    
    #endif
}

Global level means creating a file at the top level of the project. It's the same as creating a UIViewController or other project file. It will be visible project-wide so long as it's not marked private or fileprivate.

The overridden print method is called by every print statement in the project code since it's global. There's a macro definition inside the print method that checks for the DEBUG preprocessor definition.  If it's enabled, the method calls print.

Now that's complete, set up the DEBUG flag properly.

EDIT 7/31/2019: Xcode 10 made the DEBUG flag enabled so this step can be skipped. Just follow along and make sure the DEBUG flag in the project is set up correctly. Refer to the screenshot:

Screen-Shot-2019-08-26-at-10.35.38-PM

The steps to follow are below:

  1. Open the project and select the configuration in the project navigator.
  2. Select the Build Settings tab and in the search box, type custom flags.
  3. Select the dropdown next to Other Swift Flags
  4. Double-click to the right of the "+" symbol. A pop-up should open
  5. Hit the "+" button at the bottom of the popup and type "-D DEBUG"

The last step should look like this:

Screen-Shot-2019-08-26-at-10.42.37-PM

The print method is override is complete and the environment set up.

Testing

Run some tests to ensure that the print statements work in debug mode. Run the app as usual, making sure that the run mode is debug.  That option is at the top of Xcode, next to the run and stop buttons.   The name of the project and the simulator are visible.  Refer to the screenshot below:

Screen-Shot-2019-08-26-at-10.46.39-PM

The project "name" is a button that allows editing of the run schema. Click that button and select Edit Schema. You should see this:

Screen-Shot-2019-08-26-at-10.49.44-PM

Next to Build Configuration, there is a debug option. Close that and run the app, verifying the visibility of the print statements.

Now go back to the Edit Scheme and change the Build Configuration to Release. Run the app again. If no print statements were output the configuration is validated.

If there are print statements and the schema is Release, look at the following options:

  • Make sure the overridden print method is global by adding another simple method into the file and seeing if it is callable from elsewhere in your project. If that doesn't work then it's not setup globally.
  • Make sure the DEBUG flag is setup correctly. After adding it, go back to Build Settings and make sure the -D DEBUG in the Other Swift Flags section of Build Configurations.