{"id":1846,"date":"2015-06-11T08:58:56","date_gmt":"2015-06-11T07:58:56","guid":{"rendered":"http:\/\/denbeke.be\/blog\/?p=1846"},"modified":"2015-06-11T09:02:50","modified_gmt":"2015-06-11T08:02:50","slug":"creating-a-first-iphone-app-liveblog-in-swift","status":"publish","type":"post","link":"https:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/","title":{"rendered":"Creating a first iPhone app: Liveblog in Swift"},"content":{"rendered":"<p>Apple announced that Swift would become open source at the WWDC keynote (earlier this week). The perfect moment for me to create my very first iOS app (in the newly released Swift 2 and Xcode 7 beta). So I spent a few hours yesterday and created a real-time live blog app as a front-end for the WebSocket\u00a0<a href=\"http:\/\/denbeke.be\/blog\/programming\/simple-liveblog-to-demonstrate-websockets-in-go\/\" target=\"_blank\">Liveblog back-end<\/a> I&#8217;ve written in Go.<\/p>\n<h3>Xcode project<\/h3>\n<p>First I downloaded the new Xcode 7 beta, and created a new application.\u00a0<em>File, New, Project.<\/em> Select <em>iOS, Single View Application.<\/em> Fill in the needed information (make sure the select Swift as programming language and not Objective-C) and create\u00a0the project.<\/p>\n<p><a href=\"http:\/\/denbeke.be\/blog\/?attachment_id=1847\"><img loading=\"lazy\" class=\"aligncenter wp-image-1847 size-full\" src=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-create-Swift-Single-View-app.png\" alt=\"Xcode create Swift Single View app\" width=\"688\" height=\"420\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-create-Swift-Single-View-app.png 688w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-create-Swift-Single-View-app-300x183.png 300w\" sizes=\"(max-width: 688px) 100vw, 688px\" \/><\/a><\/p>\n<h3>CocoaPods<\/h3>\n<p>Since I didn&#8217;t really figured out how to import external modules from Github (and didn&#8217;t want to lose time on doing so) I used the <a href=\"https:\/\/cocoapods.org\" target=\"_blank\">CocoaPods<\/a> tool. This handy tool manages the dependencies for you. (Comparable to Composer for PHP)<\/p>\n<p>Installing CocoaPods is very simple using the Terminal:<\/p>\n<pre><code>$ sudo gem install cocoapods<\/code><\/pre>\n<p>In Terminal navigate to your project folder and execute <code>pod init<\/code> (This will create the <code>Podfile<\/code> file in the root directory of your project), and append the following content the Podfile:<\/p>\n<pre class=\"\"><code>use_frameworks!\r\n\r\ntarget 'Liveblog' do\r\n\tpod 'Starscream', '~&gt; 0.9'\r\nend\r\n<\/code><\/pre>\n<p>Now open the <code>Liveblog.xcworkspace<\/code> Workspace in Xcode. Since Starscream isn&#8217;t yet coded in Swift 2, Xcode 7 will ask the convert the code to Swift 2. After the automatic conversion, there will still be some compile errors to fix. You can fix them with auto-fix in Xcode.<\/p>\n<h3>Creating the\u00a0user interface<\/h3>\n<p>Next step is designing our iPhone app. (I&#8217;m not a designer, nor an UX expert, so I&#8217;ll keep it simple, KISS). All of this happens in the\u00a0<code>Main.storyboard<\/code> file.<\/p>\n<p>At the bottom of the right sidebar, there are some switches with pre-made things you can include into your project (including code snippets, or creating new files). We need the third tab of that panel, i.e. the panel with UX elements.<\/p>\n<h4>View<\/h4>\n<p>Our storyboard will already consist of a <em>View<\/em>, which we can style. I chose to give the main view a sea green background.<\/p>\n<h4>Label<\/h4>\n<p>Now it&#8217;s time to create a title at the top of the view. Drag a <em>label<\/em> from the right bottom UX panel to the view. Again you can do some styling at the right panel. (I increased the font size a lot, and opted for a white font)<\/p>\n<p>Now we want to center the label on all screen sizes. Therefor you can add &#8216;responsive&#8217; constraints to your storyboard elements. At the right bottom corner of the storyboard panel, there are 4 buttons. Click on the second button to add aligning constraints: select\u00a0the horizontal constraint and click on <em>&#8220;Add 1 constraint&#8221;<\/em>.<\/p>\n<p><a href=\"http:\/\/denbeke.be\/blog\/?attachment_id=1849\"><img loading=\"lazy\" class=\"aligncenter wp-image-1849 size-full\" src=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-storyboard-center-responsive.png\" alt=\"Xcode storyboard center responsive\" width=\"652\" height=\"623\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-storyboard-center-responsive.png 652w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-storyboard-center-responsive-300x287.png 300w\" sizes=\"(max-width: 652px) 100vw, 652px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h4>Text View<\/h4>\n<p>The same steps need to be followed to create a\u00a0Text View on the storyboard. Drag the <em>Text View<\/em> element from the right bottom panel to the storyboard and resize it so it fills the whole view (except the top bar). Again, we want this UI element to fit all screen sizes, so we must add some constraints so it will always cover the whole screen.<\/p>\n<p>Click on the red dashed lines in the constraints panel to &#8216;enable&#8217; the constraints, and then click on <em>&#8220;Add 4 constraints&#8221;<\/em>.<\/p>\n<p><a href=\"http:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/attachment\/xcode-storyboard-responsive-constraints-textview\/\" rel=\"attachment wp-att-1851\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-1851\" src=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-storyboard-responsive-constraints-textview.png\" alt=\"Xcode storyboard responsive constraints textview\" width=\"599\" height=\"675\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-storyboard-responsive-constraints-textview.png 599w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-storyboard-responsive-constraints-textview-266x300.png 266w\" sizes=\"(max-width: 599px) 100vw, 599px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Now launch the app in the iOS simulator and make sure everything is responsive.\u00a0If \u00a0everything looks fine, you\u00a0can remove the sample text from the TextView (since we will\u00a0load\u00a0WebSocket data in it)<\/p>\n<h4>Add referencing outlet<\/h4>\n<p>If we want to actually do something with the\u00a0<em>TextView<\/em>, we need to create a referencing outlet for it in the <code>ViewController.swift<\/code> file. In the right top navigation click on the editor icon (the two overlapping rings). This will open a second, split view with the code of the ViewController. Now press the ctrl key and drag the\u00a0<em>TextView<\/em> into the code at the right side and give the outlet a name.<\/p>\n<p><a href=\"http:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/attachment\/xcode-add-referencing-outlet\/\" rel=\"attachment wp-att-1853\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-1853\" src=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-add-referencing-outlet.png\" alt=\"Xcode add referencing outlet\" width=\"876\" height=\"352\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-add-referencing-outlet.png 876w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-add-referencing-outlet-300x121.png 300w\" sizes=\"(max-width: 876px) 100vw, 876px\" \/><\/a><\/p>\n<p><a href=\"http:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/attachment\/xcode-outlet-name\/\" rel=\"attachment wp-att-1855\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-1855\" src=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-outlet-name.png\" alt=\"Xcode outlet name\" width=\"681\" height=\"305\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-outlet-name.png 681w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-outlet-name-300x134.png 300w\" sizes=\"(max-width: 681px) 100vw, 681px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>If completed successfully, your ViewController class will look like this:<\/p>\n<pre><code>class ViewController: UIViewController {\r\n\r\n\r\n    @IBOutlet weak var textView: UITextView!\r\n    \r\n    override func viewDidLoad() {\r\n        super.viewDidLoad()\r\n        \/\/ Do any additional setup after loading the view, typically from a nib.\r\n    }\r\n\r\n    override func didReceiveMemoryWarning() {\r\n        super.didReceiveMemoryWarning()\r\n        \/\/ Dispose of any resources that can be recreated.\r\n    }\r\n\r\n\r\n}<\/code><\/pre>\n<h3>Adding the WebSockets in Swift<\/h3>\n<p>Now we can finally implement the actual WebSockets for our app. Well, not really implementing, because we will be using Starscream&#8217;s WebSocket client (as mentioned above in the section of the CocoaPods)<\/p>\n<p>First thing to do is import Starscream above the ViewController class. Next add <code>WebSocketDelegate<\/code>\u00a0in the class declaration line to indicate we are\u00a0implementing the Starscream <code>WebSocketDelegate<\/code> interface (so we can delegate the WebSocket to the ViewController).<\/p>\n<pre><code class=\"swift\">class ViewController: UIViewController, WebSocketDelegate\u00a0 {\r\n    \/\/ ... \r\n}<\/code><\/pre>\n<p>Since we defined that ViewController implements the <code>WebSocketDelegate<\/code> interface, you need to add the functions of that interface to the ViewController:<\/p>\n<pre><code class=\"swift\">\/\/ websocketDidConnect is called as soon as the client connects to the server.\r\nfunc websocketDidConnect(socket: WebSocket) {\r\n    println(\"websocket is connected\")\r\n}\r\n\r\n\/\/ websocketDidDisconnect is called as soon as the client is disconnected from the server.\r\nfunc websocketDidDisconnect(socket: WebSocket, error: NSError?) {\r\n    println(\"websocket is disconnected: \\(error!.localizedDescription)\")\r\n}\r\n\r\n\r\n\/\/ websocketDidReceiveMessage is called when the client gets a text frame from the connection.\r\nfunc websocketDidReceiveMessage(socket: WebSocket, text: String) {\r\n    println(\"got some text: \\(text)\")\r\n}\r\n\r\n\/\/ websocketDidReceiveData is called when the client gets a binary frame from the connection.\r\nfunc websocketDidReceiveData(socket: WebSocket, data: NSData) {\r\n    println(\"got some data: \\(data.length)\")\r\n}\r\n<\/code><\/pre>\n<p>Next create the websocket client with the url and the port of your back-end. Append the following code to the\u00a0<code>viewDidLoad<\/code> function:<\/p>\n<pre><code>let socket = WebSocket(url: NSURL(scheme: \"ws\", host: \"labs.denbeke.be:1234\", path: \"\/\")!)\r\nsocket.delegate = self\r\nsocket.connect()<\/code><\/pre>\n<p>At this stage we have everything in place to actually handle the incoming WebSocket messages, which are marshalled in the following JSON format:<\/p>\n<pre><code>{\r\n    \"Content\":\"But even cooler, a native iPhone app written in Swift!\",\r\n    \"Time\":1433942629\r\n}<\/code><\/pre>\n<p>To do this you need to implement the\u00a0<code>websocketDidReceiveMessage<\/code> function:<\/p>\n<pre><code class=\"swift\">func websocketDidReceiveMessage(ws: WebSocket, text: String) {\r\n\r\n    let json: NSDictionary\r\n    do {\r\n        \/\/ Parse JSON request\r\n        try json = NSJSONSerialization.JSONObjectWithData(text.dataUsingEncoding(NSUTF8StringEncoding)!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary\r\n        \r\n        \/\/ Do something with the parsed JSON data\r\n        if (json[\"Content\"] != nil) {\r\n            textView.text = (json[\"Content\"] as! String) + \"\\n\\n\" + textView.text\r\n        }\r\n        \r\n    }\r\n    catch {\r\n        print(\"Could not parse json message\")\r\n    }\r\n\r\n    \r\n    print(\"Received text: \\(text)\")\r\n}<\/code><\/pre>\n<p>The above snippet will try to parse the JSON request into a Swift dictionary\/map. If this goes without any error, the content of the message will be prepended in the <em>TextView<\/em> we created earlier.<\/p>\n<p>All together your ViewController should look like this:<\/p>\n<pre><code class=\"swift\">import UIKit\r\nimport Starscream\r\n\r\nclass ViewController: UIViewController, WebSocketDelegate  {\r\n\r\n    @IBOutlet weak var textView: UITextView!\r\n\r\n    override func viewDidLoad() {\r\n        super.viewDidLoad()\r\n        \/\/ Do any additional setup after loading the view, typically from a nib.\r\n        \/\/ padding of TextView: top, left, bottom, right\r\n        textView.textContainerInset = UIEdgeInsetsMake(8,8,4,8);\r\n\r\n        \/\/ Setup WebSocket\r\n        let socket = WebSocket(url: NSURL(scheme: \"ws\", host: \"denbeke.be:1234\", path: \"\/\")!)\r\n        socket.delegate = self\r\n        socket.connect()\r\n\r\n    }\r\n\r\n    override func didReceiveMemoryWarning() {\r\n        super.didReceiveMemoryWarning()\r\n        \/\/ Dispose of any resources that can be recreated.\r\n    }\r\n\r\n\r\n    \/\/ Interface for WebSockets\r\n\r\n    func websocketDidConnect(ws: WebSocket) {\r\n        print(\"websocket is connected\")\r\n    }\r\n\r\n    func websocketDidDisconnect(ws: WebSocket, error: NSError?) {\r\n        if let e = error {\r\n            print(\"websocket is disconnected: \\(e.localizedDescription)\")\r\n        }\r\n    }\r\n\r\n    func websocketDidReceiveMessage(ws: WebSocket, text: String) {\r\n\r\n        let json: NSDictionary\r\n        do {\r\n            \/\/ Parse JSON request\r\n            try json = NSJSONSerialization.JSONObjectWithData(text.dataUsingEncoding(NSUTF8StringEncoding)!, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary\r\n\r\n            \/\/ Do something with the parsed JSON data\r\n            if (json[\"Content\"] != nil) {\r\n                textView.text = (json[\"Content\"] as! String) + \"\\n\\n\" + textView.text\r\n            }\r\n\r\n        }\r\n        catch {\r\n            print(\"Could not parse json message\")\r\n        }\r\n\r\n\r\n        print(\"Received text: \\(text)\")\r\n    }\r\n\r\n    func websocketDidReceiveData(ws: WebSocket, data: NSData) {\r\n        print(\"Received data: \\(data.length)\")\r\n    }\r\n\r\n\r\n\r\n}<\/code><\/pre>\n<p>The complete iPhone app should look like this:<\/p>\n<p><a href=\"http:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/attachment\/liveblog-ios-iphone-app-screenshot\/\" rel=\"attachment wp-att-1845\"><img loading=\"lazy\" class=\"aligncenter size-full wp-image-1845\" src=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Liveblog-iOS-iPhone-app-screenshot.png\" alt=\"Liveblog iOS iPhone app screenshot\" width=\"391\" height=\"750\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Liveblog-iOS-iPhone-app-screenshot.png 391w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Liveblog-iOS-iPhone-app-screenshot-156x300.png 156w\" sizes=\"(max-width: 391px) 100vw, 391px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>I have uploaded the source code of the app to Github: <a href=\"https:\/\/github.com\/DenBeke\/Liveblog-iOS-App\" target=\"_blank\">Liveblog-iOS-App<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Apple announced that Swift would become open source at the WWDC keynote (earlier this week). The perfect moment for me to create my very first iOS app (in the newly released Swift 2 and Xcode 7 beta). So I spent a few hours yesterday and created a real-time live blog app as a front-end for [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[235],"tags":[124,129,257,256,258],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.6.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Creating a first iPhone app: Liveblog in Swift &ndash; DenBeke<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Creating a first iPhone app: Liveblog in Swift &ndash; DenBeke\" \/>\n<meta property=\"og:description\" content=\"Apple announced that Swift would become open source at the WWDC keynote (earlier this week). The perfect moment for me to create my very first iOS app (in the newly released Swift 2 and Xcode 7 beta). So I spent a few hours yesterday and created a real-time live blog app as a front-end for [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/\" \/>\n<meta property=\"og:site_name\" content=\"DenBeke\" \/>\n<meta property=\"article:published_time\" content=\"2015-06-11T07:58:56+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2015-06-11T08:02:50+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-create-Swift-Single-View-app.png\" \/>\n<meta name=\"twitter:card\" content=\"summary\" \/>\n<meta name=\"twitter:creator\" content=\"@MthsBk\" \/>\n<meta name=\"twitter:site\" content=\"@MthsBk\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"6 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/denbeke.be\/blog\/#website\",\"url\":\"https:\/\/denbeke.be\/blog\/\",\"name\":\"DenBeke\",\"description\":\"Mathias Beke\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/denbeke.be\/blog\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"http:\/\/denbeke.be\/blog\/wp-content\/uploads\/2015\/06\/Xcode-create-Swift-Single-View-app.png\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/#webpage\",\"url\":\"https:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/\",\"name\":\"Creating a first iPhone app: Liveblog in Swift &ndash; DenBeke\",\"isPartOf\":{\"@id\":\"https:\/\/denbeke.be\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/#primaryimage\"},\"datePublished\":\"2015-06-11T07:58:56+00:00\",\"dateModified\":\"2015-06-11T08:02:50+00:00\",\"author\":{\"@id\":\"https:\/\/denbeke.be\/blog\/#\/schema\/person\/386878f712fe3fe22227216f087772dc\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/denbeke.be\/blog\/programming\/creating-a-first-iphone-app-liveblog-in-swift\/\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/denbeke.be\/blog\/#\/schema\/person\/386878f712fe3fe22227216f087772dc\",\"name\":\"Mathias Beke\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/denbeke.be\/blog\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/015ba35e6ce4f5859e3888ca99807575?s=96&d=mm&r=g\",\"caption\":\"Mathias Beke\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts\/1846"}],"collection":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/comments?post=1846"}],"version-history":[{"count":14,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts\/1846\/revisions"}],"predecessor-version":[{"id":1865,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts\/1846\/revisions\/1865"}],"wp:attachment":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/media?parent=1846"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/categories?post=1846"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/tags?post=1846"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}