Thursday, 27 April 2017

Optionals

Introduction
Swift is a very safe language, by which I mean it works hard to ensure your code never fails in surprising ways.
One of the most common ways that code fails is when it tries to use data that is bad or missing.
Swift has a solution: optionals. An optional value is one that might have a value or might not.
What are optionals
Optional is just a type in Swift language, nothing fancy. Int and Int? (optional Int) are two different types, if your variable happens to be of type Int you can be absolutely sure it will always have an integer value, and if your variable is of type Int? it will either have an integer value or it will have no value at all (in other words, it will be nil).
Think of optional as a wrapper type. It’s like a gift box which wraps the value inside, and like a real-life box, optional can either contain something or be empty.
An optional which contains integer value of four, as if to write let myOptional: Int? = 4
An optional that doesn’t contain any value, as if to write let myOptional: Int? = nil
The high level idea of wrapping the value inside a box is that we can safely use the box without worrying what’s inside.


Under the hood optional types are merely an enum with two cases — None meaning no value is set and Some meaning the value is set and it’s the value associated with it.
enum  optional<T> {
case None
case  Some(T)
}

//These two statements are exactly the same
let x: String? = nil
let x = Optional<String>.None


//These two statements are exactly the same
let y: String? = “Hi this is malai”
let  y = Optional<String>.Some(“Hi this is malai”)

Forced Unwrapping (!)
// forced unwrapping
let b: String? = "Hi there"
var a = b!

// under the hood forced unwrapping is a switch statement
switch b {
  case .Some(let value): a = value
  case .None: //raise an exception
}
Well, because compiler doesn’t know how to add a box into an integer. In order to achieve this we need to unwrap the optional, in other words we need to open the box and extract the value inside. For that we put the “!” mark after the variable’s name meaning “I’m sure this box contains something, extract that value and use it”. This is called forced unwrapping.
Optional Binding
Like forced unwrapping, optional binding is a way of opening the box, but it does the job more cleverly and with less pollution than forced unwrapping. It allows to check the optional and extract its value into a constant or variable as part of a single action.

let optionalInt: Int? = 5
if let constantInt = optionalInt {
  print("optionalInt has an integer value of \(constantInt).")
} else {
  print("optionalInt is nil")
}
// will print "optionalInt has an integer value of 5"
Implicitly Unwrapped Optionals

let assumedInt: Int! = 123

Sometimes we’re really-really sure we’ll always have a value in our optional just after it’s set the first time. In this case there’s no need to unwrap the optional every time we want to use it, because it’s safe to assume we have a value.

// forced unwrapping


let optionalInt: Int? = 123

let forcedInt: Int = optionalInt!



// implicitly unwrapped optional

let assumedInt: Int! = 123

let implicitInt: Int = assumedInt

Nil coalescing


let  optionalInt: Int? = nil
Can be used safely by checking nil value before force unwrapping
let  result = optionalInt != nil ? optionalInt! : 0

Nil coalescing allows us to shorten this even more.
let  result = optionalInt ?? 0
Optional Chaining
Optional chaining is a feature that allows to call properties and methods on an optional that might currently be nil.

class Person {
  var bankAccount: BankAccount?
}

class BankAccount {
  var balance: Int
}

let person = Person()
if let currentBalance = person.bankAccount?.balance {
  print("Person has a bank account and its balance is \(currentBalance)")
} else {
  print("Person has no bank account")
}
// prints "Person has no bank account"

Tuesday, 25 April 2017

Webservice integration in swift

Introduction


Service integration in application is a trivial task for every programer, apple provides the API to get that task done.  NSURLSession is the key object responsible for sending and receiving HTTP requests.

from apple
"The NSURLSession class and related classes provide an API for downloading content. This API provides a rich set of delegate methods for supporting authentication and gives your app the ability to perform background downloads when your app is not running or, in iOS, while your app is suspended"

URL Session Class Hierarchy

The NSURLSession API consists of the following classes (nested to show subclass relationships):

URLSessionConfiguration

— A configuration object used when initializing the session.
"An NSURLSessionConfiguration object defines the behavior and policies to use when uploading and downloading data using an NSURLSession object. When uploading or downloading data, creating a configuration object is always the first step you must take. You use this object to configure the timeout values, caching policies, connection requirements, and other types of information that you intend to use with your NSURLSessionobject."

which comes in three flavors
  1. defaultSessionConfiguration: Creates a default configuration object that uses the disk-persisted global cache, credential and cookie storage objects.
  2. ephemeralSessionConfiguration: Similar to the default configuration, except that all session-related data is stored in memory. Think of this as a “private” session.
  3. backgroundSessionConfiguration: Lets the session perform upload or download tasks in the background. Transfers continue even when the app itself is suspended or terminated.


URLSessionTask


  • is an abstract class that denotes a task object. A session creates a task, which does the actual work of fetching data and downloading or uploading files.
There are three types of concrete session tasks in this context:

  • NSURLSessionDataTask: Use this task for HTTP GET requests to retrieve data from servers to memory.
  • NSURLSessionUploadTask: Use this task to upload a file from disk to a web service, typically via a HTTP POST or PUT method.
  • NSURLSessionDownloadTask: Use this task to download a file from a remote service to a temporary file location.
NSURLSession Tutorial
You can also suspend, resume and cancel tasks. NSURLSessionDownloadTask has the additional ability to pause for future resumption.

In addition, the NSURLSession API provides four protocols that define delegate methods your app can implement to provide more fine-grained control over session and task behavior.
Finally, the NSURLSession API uses a number of classes that are also commonly used with other APIs such as NSURLConnection and NSURLDownload. Some of these shared classes include:
  • NSURL—An object that contains a URL.
  • NSURLRequest—Encapsulates metadata related to a URL request, including the URL, request method, and so on.
  • URLResponse—Encapsulates metadata related to a server’s response to a request, such as the content MIME type and length.
    • HTTPURLResponse—Adds additional metadata specific to HTTP requests, such as response headers.
  • CachedURLResponse—Encapsulates an URLResponse object, along with the actual body data of the server’s response, for caching purposes.




Example
// Set up the URL request
let todoEndpoint: String = "https://jsonplaceholder.typicode.com/todos/1"
guard let url = URL(string: todoEndpoint) else {
 print("Error: cannot create URL")
 return
}
let urlRequest = URLRequest(url: url)

// set up the session
let config = URLSessionConfiguration.default
// let session = URLSession.shared

let session = URLSession(configuration: config)
// make the request
let task = session.dataTaskWithRequest(urlRequest) {
 (data, response, error) in
 // check for any errors
 guard error == nil else {
   print("error calling GET on /todos/1")
   print(error)
   return
 }
 // make sure we got data
 guard let responseData = data else {
   print("Error: did not receive data")
   return
 }
 // parse the result as JSON, since that's what the API provides
 do {
   guard let todo = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: AnyObject] else {
  print("error trying to convert data to JSON")
   return
 }
}
   // now we have the todo, let's just print it to prove we can access it
   print("The todo is: " + todo.description
   // the todo object is a dictionary
   // so we just access the title using the "title" key
   // so check for a title and print it if we have one
   guard let todoTitle = todo["title"] as? String else {
     print("Could not get todo title from JSON")
     return
   }
   print("The title is: " + todoTitle)
 } catch  {
   print("error trying to convert data to JSON")
   return
 }
}
task.resume()

Follow this tutorial for more concept oriented use cases