Swift from the commandline

I always find it instructive to start from the commandline. When I subsequently migrate to IDE, my feet are on the ground.


I've been trying with a basic "hello world" style Swift snippet: the challenge is to draw a window on the screen without using Xcode.


Now Swift has a compiler and an interpreter. So the challenge bifurcates -- to get it running on each.


Could someone provide a set of instructions for each, together with an explanation of what's going on?


π

Post not yet marked as solved Up vote post of p-i- Down vote post of p-i-
8.5k views

Replies

There's no interpreter. It's always the compiler.

You can put a window on the screen by creating an NSWindow object and telling it to show itself.


import Cocoa
let rect = NSRect(x:100,y:100,width:100,height:100)
let window = NSWindow(contentRect: rect, styleMask: NSTitledWindowMask, backing: .Buffered, `defer`: false)
window.makeKeyAndOrderFront(nil)


makeKeyAndOrderFront tells the window to show itself and make it the frontmost window. The "frontmost window" in this case is from what I understand relative to the application, but the command line Swift interpreter doesn't have an application, you would have to create that as well. For now, I just set the window level to 1 to make it appear:


window.level = 1


This makes it float above all windows at level 0, i.e. the normal window level.


To make something actually appear in the window, you have to make an NSView and make it draw something:


class MyView : NSView {
    override func drawRect(dirtyRect: NSRect) {
        NSColor.redColor().set()
        NSRectFill(dirtyRect)
    }
}
window.contentView = MyView()


The problem here is that you still won't see anything. I'm guessing that the reason is that the runloop is not running. Unfortunately, I don't know how to start it correctly.

Another way of drawing in the window is to not use an NSView, but draw directly into the window:


NSGraphicsContext.setCurrentContext(window.graphicsContext)
NSColor.redColor().set()
NSRectFill(NSRect(x:0,y:0,width:100,height:100))
window.flushWindow()


The steps here are:

  1. Setting the current graphics context (a global variable for the thread) to the graphics context of the window
  2. Setting the current color of the graphics context to red
  3. Filling a rectangle in the graphics context
  4. Flushing the contents so that the result is visible


And now you can show a window and draw into it only using the command line.


Even though this is possible, depending on what you want to do it is probably better to use the playgrounds in Xcode, since they work in a similiar way to a command line, but actually runs in the same kind of environment as "normal" applications.

Below is the "Webkit Browser in 30 Lines of Swift" from practicalswift.com, with some small changes to make it run on latest beta with Swift 2.

(Omitted link because this will get stuck in moderation otherwise ...)


1. Create a file called browser.swift (or whatever) containing this:

#!/usr/bin/swift
import WebKit
let application = NSApplication.sharedApplication()
application.setActivationPolicy(NSApplicationActivationPolicy.Regular)
let window = NSWindow(contentRect: NSMakeRect(0, 0, 960, 720), styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask, backing: .Buffered, `defer`: false)
window.center()
window.title = "Minimal Swift WebKit Browser"
window.makeKeyAndOrderFront(window)
class WindowDelegate: NSObject, NSWindowDelegate {
    func windowWillClose(notification: NSNotification) {
        NSApplication.sharedApplication().terminate(0)
    }
}
let windowDelegate = WindowDelegate()
window.delegate = windowDelegate
class ApplicationDelegate: NSObject, NSApplicationDelegate {
    var _window: NSWindow
    init(window: NSWindow) {
        self._window = window
    }
    func applicationDidFinishLaunching(notification: NSNotification) {
        let webView = WebView(frame: self._window.contentView.frame)
        self._window.contentView.addSubview(webView)
        webView.mainFrame.loadRequest(NSURLRequest(URL: NSURL(string: "https://forums.developer.apple.com/thread/5137")!))
    }
}
let applicationDelegate = ApplicationDelegate(window: window)
application.delegate = applicationDelegate
application.activateIgnoringOtherApps(true)
application.run()


2. Make it executable (chmod +x browser.swift).


3. Run (./browser.swift)

Post not yet marked as solved Up vote reply of Jens Down vote reply of Jens
Add a Comment

I can help you with the interpreter part. With Swift, it's called the read-evaluate-play loop (REPL), and it's accessible from both the command line and from the LLDB debugger terminal.


To open the REPL in the command line, type this command:

xcrun swift

The tool isn't downloaded by default, so you'll be prompted to download and install it.

Once you get the REPL working, just type a line of code and hit Return—it will be immediately compiled and executed and you'll be able to see the current state of your variables. I don't know if you'll be able to create a window with it, though, but it's great for learning the language.

You may design a window inside a String variable with characters as you like inside a Swift file. To run that on the terminal (i.e. command line) on MacOS, follow the steps below:

  1. Compile the program by typing: swiftc YourFileName.swift
  2. Run the program by typing: ./YourFileName

Note, Swift uses a compiler to boost the speed instead of an interpreter.

In case you are on an OS other than MacOS, kindly check OS-specific doc on using Swift at swift.org.