In my previous article about Apple’s use of Swift and SwiftUI in iOS 14, I counted the number of built-in apps in iOS using Swift and SwiftUI. Several readers asked if I could provide a percentage rather than an absolute number.

In this new article, I will answer this question by measuring the total number of binaries in iOS. I will go one step further and also count the number of binaries using other programming languages: Objective-C, C++ and C.

Finally to be as complete as possible, I ran this analysis on all major iOS releases, from iPhone OS 1.0 to iOS 14. This will provide a detailed overview of the evolution of the different programming languages over more than a decade of iOS development.

Scope

Before jumping into the analysis, let's clarify the scope. First I only analyzed what is commonly called ‘iOS’, i.e. everything above the kernel. The XNU kernel and low-level firmwares (SecureROM, Baseband, …) are not included in this analysis. On the other hand, I counted the frameworks located inside the dyld shared cache, a cache mechanism introduced in iPhone OS 3.1 and still used in iOS 14.

Another point is that you may note the absence of Objective-C++. The approach I used can't really detect binaries using Objective-C++. So I counted such binaries as using both Objective-C and C++.

Finally you should take this analysis with a grain of salt. While I believe the overall picture to be accurate, my approach has some limitations due to the simple fact that I don't have access to the iOS source code and relied on imprecise compilation artifacts.

Detecting and counting binaries

The first problem to tackle was to count the number of binaries in iOS. Because I ran the analyses off‑device, I could not rely on the permissions being properly set.

Instead I used the fact that a binary has to be a Mach-O file to be executable. Checking if a file is a Mach-O binary is trivial by using the file command line tool in a Bash script:

#---------------------------------------------------------------------
# Function to check if a file (passed as argument $1) is an executable
# It returns the number of occurrences of the string 'Mach-O' returned by
# the output of the file command. File would generally return a line like
# - Mach-O 64-bit executable arm64e (/usr/bin/sysdiagnose)
# - Mach-O 64-bit dynamically linked shared library arm64e (/usr/lib/libobjc-trampolines.dylib)
# - Mach-O 64-bit bundle arm64e (/usr/lib/xpc/support.bundle/support)
# - Mach-O 64-bit dynamic linker arm64e (/usr/lib/dyld)
# - Mach-O 64-bit kext bundle arm64e (/System/Library/Extensions/AppleIDV.kext/AppleIDV)
# - Mach-O 64-bit dynamically linked shared library stub arm64e (/Applications/FTMInternal-4.app/libMobileGestalt.dylib)
#---------------------------------------------------------------------
isExecutable ()
{
	file $1 2>/dev/null | grep -o "Mach-O" | wc -l
}

I ran this script through all the files of each major iOS release to count the number of binaries and to obtain the evolution over time:

As you can see, iPhone OS 1.0 contained quite a small amount of binaries. But iOS has become more and more complex and iOS 14.0 now contains 20 times more binaries than iPhone OS 1.0.

Detecting the different programming languages

In my previous article on Apple’s use of Swift and SwiftUI in iOS 14, I counted the built-in apps using Swift and SwiftUI. For this article I decided to go one step further and also count the number of binaries using Objective-C, C++ and C.

Keep in mind that you can mix different programming languages to create a binary. One example is to create an app that uses C++ for the low-level engine and Objective-C for the UI. Another good example is Clatters where I use some code written in Swift, SwiftUI, Objective-C and C, the most appropriate programming languages being used to solve each specific problem.

Detecting SwiftUI

In my previous post, I explained how to detect if a binary uses SwiftUI by checking if it dynamically links against /System/Library/Frameworks/SwiftUI.framework/Versions/A/SwiftUI. This can be implemented in a Bash script like:

isSwiftUI=$( echo "${otoolOutput}" | grep -o "/System/Library/Frameworks/SwiftUI\.framework/SwiftUI" | wc -l )

Although SwiftUI is not really a programming language but rather an user interface toolkit, I decided to include it in this article.

Detecting Swift

Detecting the use of Swift can be done using a similar method, as described in an older post in 2016. The script is however slightly more complex due to the fact that the Swift libraries have been moved to different locations during the history of iOS:

isSwift=$( echo "${otoolOutput}" | grep -o "/usr/lib/swift/" | wc -l )
if [ ${isSwift} == 0 ]
then
	# On iOS 11, the Swift dylib were inside "/System/Library/PrivateFrameworks/Swift/"
	isSwift=$( echo "${otoolOutput}" | grep -o "/System/Library/PrivateFrameworks/Swift/" | wc -l )
	
	if [ ${isSwift} == 0 ] && [[ $1 != */libswiftUIKit.dylib ]]
	then
		# On iOS 9, the Swift dylib were built into the app
		isSwift=$( echo "${otoolOutput}" | grep -o "@rpath/libswiftUIKit\.dylib" | wc -l )
	fi
fi

Detecting Objective-C

Detecting if a binary uses Objective-C is pretty simple as explained in Apple's documentation:

The Objective-C runtime is a runtime library that provides support for the dynamic properties of the Objective-C language, and as such is linked to by all Objective-C apps. Objective-C runtime library support functions are implemented in the shared library found at /usr/lib/libobjc.A.dylib.

A simple line can thus detect all apps using Objective-C:

isObjectiveC=$( echo "${otoolOutput}" | grep -o "/usr/lib/libobjc\." | wc -l )

Detecting C++

Similarly to Objective-C, we can rely on the fact that apps using C++ have to use the C++ standard library. On modern iOS versions, the C++ standard library libc++ is located at /usr/lib/libc++.1.dylib. On iOS 7 and earlier, the gcc's libstdc++ was used and located at /usr/lib/libstdc++.6.dylib.

In case you are wondering why the exact path is not used in the script below, the reason is to mark libc++abi.dylib as using C++. libc++abi is the low level support for the standard C++ library and appears to be written in C++.

isCPP=$( echo "${otoolOutput}" | grep -o "/usr/lib/libc++" | wc -l )
if [ ${isCPP} == 0 ]
then
	isCPP=$( echo "${otoolOutput}" | grep -o "/usr/lib/libstdc++" | wc -l )
fi

Detecting C

Without entering into complex details, Objective-C and C++ are a superset of C. This means that an Objective-C or C++ app is using C code. So we can't know if an Objective-C or C++ app is using some pure C code. However some apps are written entirely in C. These are generally low-level command line tool, like /usr/bin/zprint.

How to detect such binaries? If a binary doesn't link neither to the Objective-C runtime library nor to the C++ standard library, but uses the standard C library libc located at /usr/lib/libSystem.B.dylib, then we can assume that this binary is entirely written in C. To detect apps entirely written in C, I ended up with these lines:

isC=$( echo "${otoolOutput}" | grep -o "/usr/lib/libSystem\." | wc -l )
if [ ${isC} == 0 ]
then
	isC=$( echo "${otoolOutput}" | grep -o "/usr/lib/system/" | wc -l )
fi

You will also notice that I hardcoded all the dynamic libraries located inside /usr/lib/system/ as being written in C. These low-level libraries don't link to /usr/lib/libSystem.B.dylib but are most likely written in C.

Special cases

In the final script, you will see a couple of special cases:

  • /usr/lib/libobjc-trampolines.dylib: This library is entirely written in assembly and you can read its arm64 source code in this file objc-blocktramps-arm64.s

  • /usr/lib/dyld: dyld is the dynamic linker and is a really special binary. Since it is open source, we can easily confirm that it contains C++ code.

  • /System/Library/Caches/com.apple.xpc/sdk.dylib and /System/Library/Caches/com.apple.xpcd/xpcd_cache.dylib: These 2 libraries seem to be autogenerated libraries and part of dyld.

  • /System/Library/Extensions/*: There are a couple of (kernel?) extension used by iOS like /System/Library/Extensions/AppleIDV.kext. All these binaries appear to use C++.

Final script

You can download here the complete script that loops through all the files of a folder. This script prints the paths of all the binaries found and tells you the programming languages used, like:

/Applications/AccountAuthenticationDialog.app/AccountAuthenticationDialog |Objective-C
/Applications/ActivityMessagesApp.app/ActivityMessagesApp |Objective-C
/Applications/ActivityMessagesApp.app/PlugIns/ActivityMessagesExtension.appex/ActivityMessagesExtension |Objective-C|Swift
/Applications/AnimojiStickers.app/AnimojiStickers |Objective-C
/Applications/AnimojiStickers.app/PlugIns/AnimojiStickersExtension.appex/AnimojiStickersExtension |Objective-C
/Applications/AppSSOUIService.app/AppSSOUIService |Objective-C
/Applications/AppStore.app/AppStore |Objective-C|Swift
/Applications/AppStore.app/PlugIns/ProductPageExtension.appex/ProductPageExtension |Objective-C|Swift
/Applications/AppStore.app/PlugIns/SubscribePageExtension.appex/SubscribePageExtension |Objective-C|Swift
[...]

Raw Result

I ran this script on all major releases of iOS from iPhone OS 1.0 to iOS 14.0. If you are interested by the raw data, you can download them here:

Version Device Raw Data
iOS 14.0 (18A373) iPhone X iOS14.txt
iOS 13.1 (17A844) iPhone X iOS13.txt
iOS 12.0 (16A366) iPhone X iOS12.txt
iOS 11.1 (15B93) iPhone X iOS11.txt
iOS 10.1 (14B72) iPhone 5s iOS10.txt
iOS 9.0 (13A344) iPhone 5s iOS9.txt
iOS 8.0 (12A365) iPhone 5s iOS8.txt
iOS 7.0.1 (11A470a) iPhone 5s iOS7.txt
iOS 6.0 (10A403) iPhone 3GS iOS6.txt
iOS 5.0 (9A334) iPhone 3GS iOS5.txt
iOS 4.0 (8A293) iPhone 3GS iOS4.txt
iPhone OS 3.0 (7A341) iPhone 3GS iOS3.txt
iPhone OS 2.0 (5A347) iPhone 2G iOS2.txt
iPhone OS 1.0 (1A543a) iPhone 2G iOS1.txt

Distribution of the programming languages in iOS 14

Now that we know the total number of binaries and their programming languages, we can answer the question about the percentage of binaries using Swift and SwiftUI in iOS 14. Please note that a binary can use multiple programming languages. As such, a binary can be counted multiple times, for example in the Swift and Objective-C categories. The size and importance of the binaries are also not taken in account.

Out of all the binaries in iOS 14:

  • 88% are using Objective-C
  • 17% are using C++
  • 8% are using Swift
  • 8% are entirely written in C
  • 1% are using SwiftUI

Some interesting points:

  • Objective-C is still a critical component in iOS 14.
  • C++ and C also play an important role. These languages are generally used by binaries related to audio, video, telephony, web, and other low-level frameworks.
  • Swift has been fairly quickly adopted and is already used by 8% of the binaries in iOS 14.

Evolution of the programming languages

By running the script on all the major releases of iOS from iPhone OS 1.0 to iOS 14.0, we can see the evolution of the programming languages used by iOS. Again please note that a single binary can be counted multiple times, so the sum of the binaries is greater than the total number of binaries:

What does it tell us?

  • As we already saw, iOS is becoming more and more complex with each release.
  • iPhone OS 1.0 contained fewer binaries than the number of binaries in iOS 14.0 using Swift.
  • The usage of Swift is progressing at Apple and there are now more binaries using Swift than binaries entirely written in C. But the adoption is taking time.
  • The number of binaries using Objective-C is still growing with each iOS release.
  • The usage of C++ is also constantly growing over the years.
  • On the other hand, the number of binaries written entirely in C is now stagnating.

The evolution of each programming language might be easier to see in this graph:

WidgetKit widgets and Objective-C

While reviewing the data to ensure that they made sense, I was surprised to discover that all the new iOS 14 widgets built using WidgetKit, the first public SwiftUI-only framework, were using Objective-C.

It turns out that if you create an iOS 14 widget with a Configuration Intent, Xcode will automatically generate some files containing Objective-C classes like:

@objc(ConfigurationIntent)
public class ConfigurationIntent: INIntent {

}

As a consequence all SwiftUI widgets in iOS 14 are using at least indirectly some Objective-C code.

Conclusion

Even though we don't have access to the iOS source code, we can determine the programming languages used in iOS. This approach has obviously some limits and while I believe the overall picture to be accurate, I can't guarantee that the results are perfectly exact. If you think that I missed something, please reach me out on Twitter.

There are however a couple of conclusions that we can draw. First iOS has become more and more complex and iOS 14.0 now contains 20 times more binaries than iPhone OS 1.0.

One interesting point is that 88% of the binaries in iOS 14 rely directly or indirectly on Objective-C. Objective-C continues to be a critical programming language in iOS.

It is also worth noting that the usage of C++ is also constantly growing over the years, with 17% of the binaries using C++ in iOS 14.

Finally the usage of Swift is progressing at Apple but the adoption is taking time. In iOS 14, approximatively 8% of the binaries are using Swift.