Today, we’ll be discussing getting an older version of Xcode (7) to work with a newer version of the iOS SDK (10). When done reading this article, you’ll be able to build, link, install, and debug apps in/from Xcode 7 onto iPhones/iPads/iPods running iOS 10. (If you don’t need background, just skip to the solution.) The main reasons for doing this?
- You have an app built for the last iOS version (9) that has a problem when running in the latest iOS version (10) and you’d like to debug the code; and/or,
- Apple releases a new beta iOS (10) and beta Xcode (8), you want to see how your current, stable code (built for iOS 9) runs on the new beta iOS (10), but you don’t want to trash your current, stable Xcode (7) installation with the beta Xcode (8).
This may sound counterintuitive. For years Apple has forced developers to move forward. Remember the days when everyone scrambled to retrofit their apps before the new iOS version was released? iOS 4 to 5? iOS 5 to 6? Remember when, in 2013, Apple “said that all new apps and app updates submitted after February 1, 2014, ‘must be optimized for iOS 7’ and built with the latest version of Xcode 5” — the whole skeuomorphism thing? Since iOS 7, Apple has gotten better at backward compatibility. I have an iOS 7 app that runs fine in iOS 8.x, 9.x, and 10.x. Back to using Xcode 7 with the iOS 10 SDK…
Suppose you’ve been developing an app for the iOS 9 SDK using Xcode 7. You’ve got everything working perfectly on a bunch of Apple devices running iOS 9. But work has gone on a bit longer than expected — what a surprise in software development 😉 — and Apple’s already released iOS 10 and Xcode 8. So you think, “No problem. Gone are the days of having to fix apps before every iOS release. Apple’s gotten really good at backward compatibility.” Uh… NOT!
You put out a TestFlight release and beta testers find a bug that only occurs in iOS 10, but never in iOS 9. So you install Xcode 8 side-by-side with Xcode 7 and you upgrade several devices to Xcode 10. You find that you can’t compile your iOS 9 project in Xcode 8 — at least not without spending hours or days to figure out what subtle changes Apple made to their compiler, linker, SDK, etc. What did Apple do this time?!?!?! You try to install your app from Xcode 7 to a device with iOS 10 and Xcode says “device unavailable” and “Could not find a developer disk image.”
Let’s be precise. My app is stable when the Base SDK is iOS 9.3, the last version of iOS 9 that Apple released. The compiler/IDE is Xcode 7.3.1, the last version of Xcode 7 that Apple released. I first encountered problems when I:
- ran my app from TestFlight on iOS 10.1.1 devices; and,
- tried to build a debug version of my app project and some of its constituent library projects in Xcode 8.2.1.
- I’ll be using the the same MacOS file system paths I used in yesterday’s post, so make sure you check your own Mac’s Xcode path configurations before following along with the instructions below, especially if copying and pasting any of my code snippets.
- This is a short-term solution. Xcode 7 was not built for iOS 10. There are certain coding scenarios which will not work going forward, i.e., framework incompatibilities, Swift 3.0, deprecated features…
- Make sure all Xcode versions are closed until I explicitly ask you to open them. Make sure you open and close Xcode only when I ask you to during the following process.
Where does the iOS 10 SDK live?
The iOS 10 SDK can be found in my Xcode 8 bundle in “/Applications/Xcode.app”. A bundle is basically just a directory structure. Open up a Terminal window and follow along with my commands:
10.0 10.2 (14C89) 8.1 8.3 9.0 9.2
10.1 8.0 8.2 8.4 9.1 9.3
My “ls” command shows that the iOS 10 SDKs (10.0, 10.1, and 10.2) are just directories and are already installed on my Mac.
So all you have to do is make the iOS 10 SDK(s) available to Xcode 7. Here’s how:
1) If you haven’t already done so, install Xcode 8 side-by-side with Xcode 7. Get your development devices ready for iOS 10 and Xcode 8. Install iOS 10.x on at least one of your devices. Start Xcode 8 and connect your Apple device to your Mac. Wait until the Xcode 8’s “Toolbar” (top, center sub-window) finishes “Indexing | Processing Files”. Close Xcode 8. NOTE: Make sure you always only run one version of Xcode at a time.
2) You can copy an iOS 10 SDK (like directory “10.2 (14C89)”) into the same relative location/path for Xcode 7, or even better,
3) Create a symbolic link from an iOS 10 SDK directory in the Xcode 8 bundle to the Xcode 7 bundle as follows:
sudo ln -s /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/10.2\ \(14C89\) /Applications/Xcode73/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/10.2
Now take a look in your Xcode 7 bundle:
lrwxr-xr-x 1 root admin 97 Jan 2 15:07 10.2 -> /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport/10.2 (14C89)
4) Start Xcode 7 and connect your Apple device to your Mac. Wait until the Xcode 7’s “Toolbar” (top, center sub-window) finishes “Indexing | Processing Files”. Build, install, and run an app from Xcode 7 on an iOS 10 device. It works! Build, install, and run an app from Xcode 7 on an iOS 9 device. It works!
NOTE: As far as I can tell, the Xcode 7 user interface will not show you that the iOS 10 SDK is available. After all, iOS 10 wasn’t even around when Xcode 7 was developed.
Now it’s time to debug my project and find out why it will run on iOS 9, but not on iOS 10.
Hope this helps. Enjoy!