Swift

Swift is an object-oriented programming language designed for a complete replacement of both the C and Objective-C, pre-bundled with all of the Cocoa (OS X) and Cocoa Touch (iOS) frameworks.

Less Syntax, More Concepts

Swift Notes

First clicks

  1. We can mix-n-match the Objective C with Swift
  2. Swift apps works on iOS 7+ and OSX Mav+
  3. Swift use same object model as Objective C
  4. Swift use the same memory management as the Objective C
  5. XCode auto translate the Objective C headers to Swift headers on its own
  6. We can create documentations in playgrounds as well

Basics

  1. Main function not needed because code are written at global scope.
  2. Use "println()" for logs
  3. Use "\()" to print variable in logs e.g;
      var anyInt = 0;  var anyString = ""; var anyDouble = 0.0;
    println("we can print any kinda var in \(anyVar)  \(anyString)  \(anyDouble)")
    
  4. We don't need to add semicolons if we are not writing in same line, Like above example ^

Constant and Variables

  1. Use "let" to init a constant and "var" to init a variable.
  2. We can declare commas separated multiple constants and variables in a single line.
  3. For constant and variable names we can use any character which not begin with a number, except mathematical symbols, arrows, line- and box-drawing characters
  4. Swift is a Type safe and Type inference language. All vars can take its type by its initial value, e.g;
      let strVar = ""
    let intVar = 0
    let doubleVar = 0.0
    
  5. We can define Type aliases with the "typealias" keyword e.g;
      typealias nonNegativeShortNumber = UInt8
    
  6. We can cast Explicit vars types by adding colon, e.g;
      let expStr: String = "70"
      
  7. We can cast Optional-Explicit vars by adding question mark, e.g;
      var expStr: String? = nil
      
  8. We need to place an exclamation mark (!) after an optional value to force the unwrapping of its value
  9. Tuple (a data structure that has a specific number and sequence of elements) support, e.g;
    let http404 =  (404, "Internet address cannot be found.")
    //We can name the individual elements
    let http200 = (statusCode: 200, description: "OK")
    //Access code without name and ignore a part of the tuple with an underscore
    let (code, _) = http404
    println("The http200 statusCode is \(http200.statusCode) and http404 code is \(code)")
    
  10. We can create arrays and dictionaries using brackets (Swift supports literals) i.e; array as [] and dictionary as [:]
  11. Dictionary instance is always being copied when assigned to another variable
  12. Array instance are not being copied when:
    • Assigned a constant or variable
    • Passed as an argument to a function or method call
  13. Array is beight copied when:
    1. We do modify the array’s length
    2. Force copy with ".copy()" method
    3. We call the ".unshare()" method
  14. We can check copy with Identity operators (=== and !==)
  15. Once a variable is defined with an enum value we can later use only dot "." syntax to chnage the value e.g;
      enum CompassPoint { case North;  case South; case East; case West }
      var directionToHead = CompassPoint.West
      directionToHead = .East
    
  16. Lazy Stored Properties is decleared with keyword "@lazy" and its initial value is not calculated until the first time it is used. Its useful when;
    • Initial value is dependent on outside factors whose values are not known until after an instance’s initialization is complete
    • Initial value requires complex or computationally expensive setup that should not be performed unless or until it is needed
    • Initializing a global constants and variables (by default all of globals are Lazy)

Conditions and Loops

  1. Swift has four loops:
    • for
    • for-in
    • while
    • do-while
  2. Swift has four control transfer statements:
    • break
    • return
    • continue
    • fallthrough (its opposite to the break statement, fallthrough is quite usefull in this language because Swift don't need a break statement in switch cases)
  3. Only boolean expression are supported in if statements, we can use Optional binding i.e;
      if let constantName = someOptionalVar {
        //do some work with constantName
      }
      // or we can still treat an implicitly unwrapped optional like a normal optional
      if someOptionalVar {
        //do some work with someOptionalVar
      }
    
  4. No need to use brackets in if conditions for single statement
  5. Switch case don't require the break keyword.
  6. Switch is powerful enough to handle any kind of data
  7. Switch case don't support cross datatype check, i.e; "1"==1
  8. Swicth case supports "where" clause, Value Bindings and Range Matching
  9. Switch case always need a default case and each case must contain at least one executable statement.
  10. Switch case support wide variety of comparison operations case including Tuples, e.g;
      let somePoint = (1, 1)
      switch somePoint {
      case (0, 0):
          println("(0, 0) is at the origin")
      case (_, 0):
          println("(\(somePoint.0), 0) is on the x-axis")
      case (0, _):
          println("(0, \(somePoint.1)) is on the y-axis")
      //demonstrating range matching
      case (-2...2, -2...2):
          println("(\(somePoint.0), \(somePoint.1)) is inside the box")
      //demonstrating where clause and value bindings
      case let (x, y) where x == y:
        println("(\(x), \(y)) is on the line x == y")
      case let (x, y) where x == -y:
        println("(\(x), \(y)) is on the line x == -y")
      //demonstrating compulsory default case
      default:
          println("(\(somePoint.0), \(somePoint.1)) is outside of the box")
      }
    
  11. We can use .. to make a range, i.e;
        let n = 9;
        for i in 0..n {
          //this will run 9 times
        }
      

Object-Oriented Part

  1. Swift have very small diffrence between Classes and Structures but they suited to different kinds of tasks. Keep in mind that; Structure instances are passed by value and Class instances are passed by reference
  2. We can nest enumerations, classes and structures within their definitions. its known as Nested Types
  3. We can define Functions (which are more like Java Lambda Expressions) with "func" and Closures with "{}" (Closures in Swift are similar to blocks in C and Objective-C) e.g;
      let user = {
        (name: String, age: Int) -> String in
        return "Name: "+name+", Age: "+String(age);
      }
      user("Gaurav", 28)
    
  4. Unlike ObjectiveC, External Parameter Names are optional in Swift and it also supports Shorthand External Parameter Names with keyword "#" e.g;
      //Function with external parameter names
      func someFunction(externalParameterName localParameterName: Int){
        //externalParameterName is for easy reference and its a good practice to define it in public - multiple param functions
      }
      //Same function with shorthand external parameter names
      func someFunction(#externalParameterName : Int){
        //here localParameterName exposed and replaced as externalParameterName with the help of # keyword
      }
    
  5. Functions supports In-Out Parameters (functions that can modify a parameter’s value) with "inout" keyword e.g;
    func swapFirstAndLastName(inout fName: String, inout lName: String) {
          let temp = fName
          fName = lName
          lName = temp
      }
      var firstName = "Gaurav"
      var lastName = "Singh"
      swapFirstAndLastName(&firstName, &lastName)
    
  6. Func can have multiple return values as well as multiple param. e.g;
    func userPlus(name: String, age: Int, weight: Double) -> (String, Int, Double) {
      return ("user name: "+name, age + 1, weight + 0.1) 
    }
    
  7. Functions supports Variadic Parameters (can also take n number of arguments of same kind) by adding "..." e.g;
    func userNames(names: String...) {  }
    
  8. Functions can be nested, can return a function, can take function as argument and supports Trailing Closures. e.g;
      func userData() -> (String, Int, Double) {
        return ("Guarav", 28, 3.79)
      }
      var name: String ? = nil
      var age: Int = 0
      var weight: Double = 0.0
      (name, age, weight) = getGasPrices()
    
  9. A class can be simply created by using class keyword, it can have multiple init with unique params and a deinit method to perform some tasks while initialization and deinitialization
  10. We can use the Type check operators to check kind of class, i.e;
    • is to check whether an instance is of a certain subclass type or not
    • as to force downcasting
    • as? to downcast in optional case
  11. Swift provides Any (for all instances except function types) and AnyObject (for instance of a class only) type aliases for working with non-specific types, its not recommended for often use
  12. There are two kinds of initializers for class types "Designated initializers (main initializers>) and Convenience initializers (supporting initializers)
  13. To declear convenience initializers use "convenience" keywork infront of the method e.g;
    class User {
      var name: String
      init(name: String) {
          self.name = name
      }
      convenience init() {
          self.init(name: "[Unnamed]")
      }
    }
    //init with convenience
    var U = User()
    //init with designated
    U = User(name:"Gaurav")
    
  14. We can also do memberwise initializers for structure types, e.g;
    struct User { var fName = "", lName = "" }
    let UserName = User(fName: "Gaurav", lName: "Singh")
    
  15. Superclass methods should be override using "override"
  16. We can prevent overrides with "@final" keywork e.g; @final var, @final func, @final class func and @final subscript
  17. Getter & Setter method are quite interesting and introduced in Swift as "Shorthand Declaration", i.e;
    let int = 10
    class plusTwo{
        var _val: Int = 0
        var val: Int {
            get {
                //getter method
                return _val
            }
            set {
                //setter method
                //the new value has the implicit name newValue
                _val = newValue + 2
            }
            /*
            willSet {
                //code that will run before setting a new value
            }
            
            didSet {
                //code that will run after setting a new value
                _val = 0
            }
            */
        }
        init (v: Int) {
            //init method
            _val = v;
            
        }
        deinit{
            //deinitializer method
        }
    }
    var p2 = plusTwo(v: 0);
    p2.val = int
    p2.val //setter will add plus two in the same
    
  18. Enum can have methods in them
  19. Enum value types can be different for each member of the enumeration (its also known as discriminated unions, tagged unions, or variants in other programming languages)
  20. Use the toRaw and fromRaw functions to convert between the raw value and the enumeration value.
  21. Classes, enumerations, and structs can all adopt Protocols
  22. Use "mutating" keyword before a method so that it can modify the properties of the structure or enumeration in future
  23. ---
  24. An Extension can be simply declared by "extension" keyword, its more like an class extension or a category without name
  25. With "extension" keyword we can make an existing type conform to more protocols and add new
    • properties
    • methods
    • initializers
    • subscripts and
    • nested types
  26. Generic functions (more like Java Generics) are written in terms of to-be-specified-later types that are then instantiated when needed for specific types provided as parameters, e.g;
  27. We can make generic forms "<...>" of functions and methods, as well as classes, enumerations, and structures.
  28. We can use "where" statement to specify a list of requirements e.g;
    • To require the type to implement a protocol
    • To require two types to be the same
    • To require a class to have a particular superclass
  29. Subscripts, yet another bingo concept by Swift:
    • Classes, structures and enum can define it
    • It is shortcut for accessing the member elements of a collection, list or sequence
    • You get/set elements in an instance as anObject[index], aDictionary[key], anArray[key]
    • Bounced off? e.g:
    class HelloUser {
        let message: String = ""
        var val = Dictionary ()
        subscript(key: String) -> String {
        get {
        // return an appropriate subscript value here
        return val[key]!
        }
        set {
        // perform a suitable setting action here
        val[key] = message+newValue
        }
        }
        init(msg: String){
            message = msg
        }
    }
    let hU = HelloUser(msg: "Hello ")
    hU.message
    hU["user1"] = "Gaurav"
    println(hU["user1"]) //this will print "Hello Gaurav"
    hU["user2"] = "Nikhil"
    println(hU["user2"]) //this will give "Hello Nikhil"
    

..WIP

Post a Comment