Nate Cook
Nate Cook

Reputation: 93296

How can I retrieve Swift "header" files for Cocoa APIs?

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?

Upvotes: 16

Views: 3232

Answers (4)

SomeRandomiOSDev
SomeRandomiOSDev

Reputation: 184

As of Xcode 12.5 the accepted answer no longer works as the -deprecated-integrated-repl flag is no longer supported. Going off of @jtbandes's answer, the following works for me with Xcode 12.5:

// iOS
echo "import UIKit\n:type lookup UIKit" | swift -sdk /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.5.sdk -target arm64-apple-ios14.5

// macOS
echo "import AppKit\n:type lookup AppKit" | swift -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -target x86_64-apple-macosx11.3

// tvOS
echo "import UIKit\n:type lookup UIKit" | swift -sdk /Applications/Xcode.app/Contents/Developer/Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS14.5.sdk -target arm64-apple-tvos14.5

// watchOS
echo "import WatchKit\n:type lookup WatchKit" | swift -sdk /Applications/Xcode.app/Contents/Developer/Platforms/WatchOS.platform/Developer/SDKs/WatchOS7.4.sdk -target arm64_32-apple-watchos7.4 

// macCatalyst
echo "import UIKit\n:type lookup UIKit" | swift -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk -target x86_64-apple-ios14.5-macabi -Fsystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.3.sdk/System/iOSSupport/System/Library/Frameworks

Of course this is going to look slightly different for whichever SDKs you have installed on your machine, but everything else in the commands are the same.

Upvotes: 1

jtbandes
jtbandes

Reputation: 118761

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

Upvotes: 6

drewag
drewag

Reputation: 94793

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

Upvotes: 13

jtbandes
jtbandes

Reputation: 118761

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.

Upvotes: 4

Related Questions