Using private APIs can be fun. When working with private APIs, I usually prefer to write code in Objective-C, since the runtime makes it a lot easier to use classes and call methods Apple doesn’t want you to. That’s of course when I’m working in Xcode on my Mac.
But what if I want to use my other computer? You know, the one I can carry with me a lot more easily than my 15” MacBook Pro. I just recently got the new 12” iPad Pro and I wanted to do some hacking with private APIs on the go. It’s not as convenient as using ObjC and Xcode on a Mac, but it can be done. I’m going to share what I found in this brief article.
The best way to interact with native iOS API on iOS itself is Swift Playgrounds. It supports most built-in frameworks and you can pretty much write anything you want using the app.
To use private APIs tho, you have to interact with the runtime, and that can become very verbose and ugly in Swift. The following is an example of how to load a private framework, instantiate and show one of its view controllers using Swift Playgrounds on iPad:
import PlaygroundSupport import UIKit import ObjectiveC assert(Bundle(path: "/System/Library/PrivateFrameworks/AvatarUI.framework")!.load()) let AVTSplashScreenViewController = NSClassFromString("AVTSplashScreenViewController") as! UIViewController.Type PlaygroundPage.current.liveView = AVTSplashScreenViewController.init()
This is what you get when you run the code above:
That’s great, but as soon as you want to do more complex things, you start having to use
performSelector, etc and that can be quite ugly. I generally use Swift Playgrounds only for very simple tests when dealing with private APIs.
$objc("ClassNameHere"). You can invoke any method with
invoke("method:name:here:", arg0, arg1, arg2) and the app itself provides lots of utilities for UI development and for calling into other iOS APIs.
Another advantage of JSBox is that it supports Shortcuts and has an intents UI extension, so you can write a JSBox script and invoke it via Shortcuts without having to launch the app for the script to run. You can even show UI inside the Siri interface. Here’s an example, showing how you can create a JSBox script that renders the Face ID unlock animation:
This is the result:
Pythonista is another great option since it allows you to call native APIs with an Objective-C bridge. Between the three options I’m showing in this article, I think Pythonista offers the best syntax for calling ObjC methods.
Here’s how you can write a Pythonista script that shows the iOS power down UI when run:
And here’s the result:
The best development environment to work with private APIs is still Xcode on the Mac, but there’s a lot that can be done on iOS, especially the iPad. Of the three options shown in this article, it is hard to name a favorite because each one has advantages and disadvantages, but the one I’ve been using the most, especially because of its flexibility and integration with Shortcuts, is JSBox.
I hope this article has been helpful. As always, you can reach me on Twitter.