tegi
2/11/2018 - 9:11 AM

Swift

Swift

Swift

Contents:

Setup

  • OS: OS X El Capitan v10.11.6
  • Xcode: v8.3

Install the latest version of Xcode from iTunes.

You can check swift version by running the following in your terminal:

$ xcrun swift -version
Apple Swift version 3.1 (swiftlang-802.0.48 clang-802.0.38)
Target: x86_64-apple-macosx10.9

Playground

  1. Open Xcode.
  2. Open a playground.
import UIKit

var str = "Hello, playground"       // "Hello, playground"

Constants, Variables and Optionals

Constants

let str = "This is constant"
let other_str: String = "Another constant"

Variables

var gender: Character
var address: String
var age: Int
var price: Float
var rate: Double
var active: Bool
var street: String = "This is a variable"
var str = "This is a variable"

Optionals

var str: String?
str = "foo"
print(str!)              // "foo\n"

Interpolation

var foo = "Test string"
print("Some string")     // => "Some string\n"
print(foo)
print(10 * 50)
print("This is interpolated with \(foo)")

Datatypes

Arrays

var array3 = ["Apple", "Pear", "Orange"]
array3.append("Cherry")                   // ["Apple", "Peach", "Orange", "Cherry"]
array3.insert("Prune", at: 2)             // ["Apple", "Peach", "Prune", "Orange", "Cherry"]
array3                                    // ["Apple", "Peach", "Prune", "Orange", "Cherry"]

Dictionaries

var dictionary1: Dictionary<String, Int>
var dictionary2: [String: Int]
var dictionary3 = ["Apple": 3, "Pear": 8, "Orange": 11]      // ["Pear": 8, "Orange": 11, "Apple": 3]

dictionary3.removeValue(forKey: "Pear")                      // 8
dictionary3                                                  // ["Orange": 11, "Apple": 3]

Sets

var set1: Set<String>
var set2 = Set<String>()                                // Set([])
var set3: Set<String> = ["Apple", "Pear", "Orange"]     // {"Pear", "Orange", "Apple"}

set3.insert("Prune")
set3                                                    // {"Pear", "Orange", "Apple", "Prune"}

set3.remove("Pear")                                     // "Pear"
set3                                                    // {"Orange", "Apple", "Prune"}

set3.contains("Orange")                                 // true

Tuples

import Foundation

var currency = ("EUR", 0.81)                      // (.0 "EUR", .1 0.8100000000000001)
var email = ("Bart Jacobs", "bart@example.com")   // (.0 "Bart Jacobs", .1 "bart@example.com")
var currency = (name: "EUR", rate: 0.81)          // (.0 "EUR", .1 0.8100000000000001)
currency.name                                     // "EUR"
currency.rate                                     // 0.8100000000000001

Conditionals

if

if foo > bar {
  print("something")
} else if foo < bar {
  print("something else")
} else {
  print("nothing")
}

switch

let a = 10

switch a {
case 0:
  print("a is equal to 0")
case 1:
  print("a is equal to 1")
default:
  print("a has another value")
}
let a = 10

switch a {
case 0..<5:
  print("The value of a lies between 0 and 4.")
case 5...10:
  print("The value of a lies between 5 and 10.")         // "The value of a lies between 5 and 10.\n"
default:
  print("The value of a is greater than 10.")
}

We can match patterns as below:

let latlng = (34.15, -78.03)

switch latlng {
case (0, 0):
  print("We're at the center of the planet.")
case (0...90, _):
  print("We're in the Northern hemisphere.")           // "We're in the Northern hemisphere.\n"
case (-90...0, _):
  print("We're in the Southern hemisphere.")
default:
  print("The coordinate is invalid.")
}

Value binding can be done as follows:

var response = (200, "OK")

switch response {
case (200..<400, let description):
  print("The request was successful with description \(description).")       // "The request was successful with description OK.\n"
case (400..<500, let description):
  print("The request was unsuccessful with description \(description).")
default:
  print("The request was unsuccessful with no description.")
}

Loop

for ... in

let numbers = [1, 2, 3, 5, 8]

for number in numbers {
  print("number is equal to \(number)")
}
var bids = ["Tom": 100, "Bart": 150, "Susan": 120]

for (name, bid) in bids {
  print("\(name)'s bid is $\(bid).")
}

while

while foo < bar {
  print("something")
}

repeat ... while

repeat {
  print("something")
} while foo < bar

Functions

Without arguments

func printHelloWorld() {
  print("Hello World!")
}

printHelloWorld()                 // Hello World!

With arguments

func printMessage(message: String) {
  print(message)
}

printMessage(message: "OK!")                  // OK!

You can make label optional when calling the functions.

func printMessage(_ message: String) {
  print(message)
}

printMessage("OK!")                           // OK!

Default arguments

import UIKit

func printDate(date: Date, format: String = "MM/dd/YYYY") {
  let dateFormatter = DateFormatter()
  dateFormatter.dateFormat = format
  print(dateFormatter.string(from: date))
}

printDate(date: Date())                               // 04/12/2017
printDate(date: Date(), format: "MM/dd")              // 04/12

Return value

import UIKit

func formatDate(date: Date, format: String = "MM/dd/YYYY") -> String {
  let dateFormatter = DateFormatter()
  dateFormatter.dateFormat = format
  return dateFormatter.string(from: date)
}

let formattedDate = formatDate(date: Date())
print(formattedDate)                                  // 04/12/2017
import UIKit

func timeComponentsFromDate(_ date: Date) -> (hour: Int, minute: Int, second: Int) {
  let dateComponents = Calendar.current.dateComponents([.hour, .minute, .second], from: date)
  let hour = dateComponents.hour
  let minute = dateComponents.minute
  let second = dateComponents.second
  return (hour ?? 0, minute ?? 0, second ?? 0)
}

print(timeComponentsFromDate(Date()))                           // (hour: 1, minute: 5, second: 15)
let components = timeComponentsFromDate(Date())
print(components.hour)                                          // 1
print(components.minute)                                        // 5
print(components.second)                                        // 15
import UIKit

func timeComponentsFromDate(_ date: Date) -> (Int, Int, Int) {
  let dateComponents = Calendar.current.dateComponents([.hour, .minute, .second], from: date)
  let hour = dateComponents.hour
  let minute = dateComponents.minute
  let second = dateComponents.second
  return (hour ?? 0, minute ?? 0, second ?? 0)
}

print(timeComponentsFromDate(Date()))                   // (1, 6, 51)
let components = timeComponentsFromDate(Date())
print(components.0)                                     // 1
print(components.1)                                     // 6
print(components.2)                                     // 51

External parameter names

func printMessage(message msg: String) {
  print(msg)
}

printMessage(message: "Hello!")                         // Hello!

Variables inside a function

func printMessage(message msg: String) {
  var msg = msg
  msg = "New value"
  print(msg)
}

printMessage(message: "Hello!")                         // New value

Variadic parameters

func sum(_ args: Int...) -> Int {
  var result = 0
  for a in args {
    result += a
  }
  return result
}

sum(1, 3, 4, 5)                       // 13

In-out parameters

func prefixString(_ string: inout String, prefix: String) {
  string = prefix + string
}

var input = "world!"

prefixString(&input, prefix: "Hello ")

input         // "Hello world!"

Nested functions

func printMessage(_ msg: String) {
  let a = "Hello world!"
    
  func printHelloWorld(){
    print(a)
  }
    
  printHelloWorld()
}

printMessage("")        // Hello world!

Functions as parameters

func prefixHello(_ msg: String) {
  var msg = "Hello " + msg
  print(msg)
}

func sayHello(_ msg: String, function: (String) -> ()) {
  function(msg)
}

sayHello("JD", function: prefixHello)           // Hello JD

Closures

import UIKit

var states = ["California", "New York", "Texas", "Alaska"]

let abbreviatedStates = states.map({ (state: String) -> String in
  let index = state.index(state.startIndex, offsetBy: 2)
  return state.substring(to: index).uppercased()
})

print(abbreviatedStates)                        // ["CA", "NE", "TE", "AL"]

You can also use shorthand argument names, $0, $1, etc.

import UIKit

var states = ["California", "New York", "Texas", "Alaska"]

let abbreviatedStates = states.map({ $0.substring(to: $0.index($0.startIndex, offsetBy: 2)).uppercased() })

print(abbreviatedStates)                        // ["CA", "NE", "TE", "AL"]

Classes

class Person {
  var firstName: String?
  var lastName: String?
  let birthPlace: String

  init(birthPlace: String) {
    self.birthPlace = birthPlace
  }
    
  func fullName() -> String {
    var parts: [String] = []
    if let firstName = self.firstName {
      parts += [firstName]
    }
    if let lastName = self.lastName {
      parts += [lastName]
    }
    return parts.joined(separator: " ")
  }
}

let john = Person(birthPlace: "USA")
john.birthPlace                                   // "USA"
john.firstName = "John"
john.lastName = "Cena"
john.fullName()                                   // "John Cena"

Inheritance

class Student: Person {
}

let student = Student(birthPlace: "India")
student.birthPlace                                // "India"

Create a project

Launch Xcode and select Create a new Xcode Project. From the iOS section, choose Single View Application template and click Next.

Now, name the project and set language to Swift. Select the Team. Make sure devise is set to iPhone and all the checkboxes at the bottom are unchecked. Click Next to continue.

Select location where the project will be saved and click Create.

In your Xcode project, open up Main.storyboard and drag in a Table View object from bottom right panel of the window. If you run the app at this point, you should see an empty table view.

Now, we need to setup a delegate and data source for the table view. Hold ctrl key, click on the table view, click on radio button to the right of Outlets -> dataSource, drag the + sign to ViewController object in storyboard's hierarchy.

Repeat above steps for Outlets -> delegate.

// ViewController.swift
import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section:Int) -> Int {
        return 10
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "MyTestCell")
        
        cell.textLabel?.text = "Row #\(indexPath.row)"
        cell.detailTextLabel?.text = "Subtitle #\(indexPath.row)"
        return cell
    }

}

Now, running your app should display a table with 10 rows. Each row will have a title Row #*, and a subtitle Subtitle #*.

Keep yourself updated

Read more