NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

Target environment testing

Available from Swift 4.1

Paul Hudson      @twostraws

Swift 4.1 implemented SE-0190, which introduced a new targetEnvironment condition that lets us differentiate between builds that are for physical devices and those that are for a simulated environment.

At this time targetEnvironment has only one value, simulator, which will be true if your build is targeting a simulated device such as the iOS Simulator. For example:

#if targetEnvironment(simulator)
   // code for the simulator here
   // code for real devices here

This is useful when writing code to deal with functionality the simulator doesn't support, such as capturing photos from a camera or reading the accelerometer.

As an example, let's look at processing a photo from the camera. If we're running on a real device we'll create and configure a UIImagePickerController() to take photos using the camera, but if we're in the simulator we'll just load a sample image from our app bundle:

import UIKit

class TestViewController: UIViewController, UIImagePickerControllerDelegate {
   // a method that does some sort of image processing
   func processPhoto(_ img: UIImage) {
       // process photo here

   // a method that loads a photo either using the camera or using a sample
   func takePhoto() {
      #if targetEnvironment(simulator)
         // we're building for the simulator; use the sample photo
         if let img = UIImage(named: "sample") {
         } else {
            fatalError("Sample image failed to load")
         // we're building for a real device; take an actual photo
         let picker = UIImagePickerController()
         picker.sourceType = .camera
         vc.allowsEditing = true
         picker.delegate = self
         present(picker, animated: true)

   // this is called if the photo was taken successfully
   func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
      // hide the camera
      picker.dismiss(animated: true)

      // attempt to retrieve the photo they took
      guard let image = info[UIImagePickerControllerEditedImage] as? UIImage else {
         // that failed; bail out

      // we have an image, so we can process it
Hacking with Swift is sponsored by Play

SPONSORED Play is the first native iOS design tool created for designers and engineers. You can install Play for iOS and iPad today and sign up to check out the Beta of our macOS app with SwiftUI code export. We're also hiring engineers!

Click to learn more about Play!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Other changes in Swift 4.1…

Download all Swift 4.1 changes as a playground Link to Swift 4.1 changes

Browse changes in all Swift versions

Unknown user

You are not logged in

Log in or create account

Link copied to your pasteboard.