Home » Swift » How can I retrieve Swift “header” files for Cocoa APIs?

How can I retrieve Swift “header” files for Cocoa APIs?

Posted by: admin November 30, 2017 Leave a comment

Questions:

The way I know I can view the automatically-translated Swift versions of Cocoa APIs is by command-clicking a Cocoa type in Xcode. For example, here’s what is generated for UITableViewController:

class UITableViewController : UIViewController, UITableViewDelegate, NSObjectProtocol, UIScrollViewDelegate, UITableViewDataSource {

    init(style: UITableViewStyle)

    var tableView: UITableView!
    var clearsSelectionOnViewWillAppear: Bool // defaults to YES. If YES, any selection is cleared in viewWillAppear:

    var refreshControl: UIRefreshControl!
}

Is there an alternate way to make Xcode generate this Swift version? Preferably from the command line?

Answers:

The Swift REPL includes a helper :print_decl <name> - print the AST representation of the named declarations

This blog post explains how you can write a simple script to help you use this to generate documentation for a specific type. I updated the script to allow using either OS X

#! /bin/sh
# usage: <shellscript> [--osx] typename

if [ "$1" = "--osx" ] ; then
    echo "import Cocoa\n:print_decl $2" | xcrun swift -deprecated-integrated-repl
else
    sdk_path=$(echo `xcrun --show-sdk-path` | sed 's#MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk#iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk#')
    echo "import UIKit\n:print_decl $1" | xcrun swift -deprecated-integrated-repl -sdk "$sdk_path"
fi

Note 1: The script defaults to using the iOS SDK. If you want to use the OS X SDK use the “–osx” option as the first parameter

Note 2: I prefer to leave out the file output that is part of the blog post so that I can use this script in other ways than just file generation

Questions:
Answers:

It turns out the modern (non-“deprecated”) REPL has a way of doing this too. Rather than :print_module, you can use :type lookup:

echo -e "import CoreGraphics\n:type lookup CoreGraphics" | swift

Questions:
Answers:

As noted in this question, the “headers” are generated from the compiled Swift modules. These are located at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos/ where there are both swiftdoc and swiftmodule files, as well as the dylibs that contain the actual libraries.

There don’t seem to be any tools to parse these at the time being. class-dump and otool are of no use. After some investigation, it seems Xcode communicates with SourceKitService (located at ...XcodeDefault.xctoolchain/usr/lib/sourcekitd.framework/XPCServices/SourceKitService.xpc
) via XPC in order to get these headers — the best approach would probably be to try and duplicate those messages for yourself. Creating a DTrace instrument in Instruments, you can see a little bit of what’s going on (this is when I -clicked on CIFilter):

dtrace

And with otool we can see that SourceKitService has symbols such as SwiftInterfaceGenContext and swift::ide::SyntaxModelWalker which are probably related to all this. But it would take a lot of work to suss out exactly what messages are being passed and how you could get the headers yourself. Probably not worth it!

Edit: drewag’s answer above shows that swift -integrated-repl‘s :print_decl command can produce the headers.