The answer to life the universal and everything

let deepThought = {(ask question: String) in
	return "The answer to\"\(question)\" is \(7 * 6)!"}

deepThought(ask: "how old are you")

Adding closures to an Array

let sum = {(a:Int, b:Int) -> Int in return a + b}
let sumf = {(a:Float, b:Float) -> Float in return a + b}

let closures = [sum, sumf]
func foo(x:Int) -> Int{
	return 42 + x
}

let bar = {(x: Int) -> Int
	in
	42 + x
}
func curly(n:Int) -> Int{
	return n * n
}

func larry(x: Int) -> Int{
	return x * (x + 1)
}

func moe(m: Int) -> Int{
	return m * (m - 1) * (m - 2)
}

var stooges = [curly, larry, moe]
stooges.append(bar)

for stooge in stooges{
	stooge(42)
}

func baz(x:Int)->Double{
	return Double(x) / 42
}

type Alias

//: Typealias

typealias Integer = Int

let z: Integer = 42
let zz: Int = 42

// (Int)->Int
typealias IntToInt = (Int)->Int

typealias IntMaker = (Void)->Int

Grand Central Dispatch(GCD)

Apple’s GCD (long form: Grand Central Dispatch) framework allows you to create asynchronous apps for iOS, ensuring smooth a smooth user experience in situations like the one mentioned above.

Flying First Class
-Return from functions or closures
-Receive as parameters of functions and closures
First-Class Types
-Assign to variables and constants
-Add to Arrays or Dictionaries

//: First Class

import UIKit

let f = {(x:Int) -> Int
	in
	return x + 42}

f(9)
f(76)

let closures = [f,
	{(x:Int) -> Int in return x * 2},
	{x in return x - 8},
	{x in xx * x},
	{$0 * 42}]

for fn in closures{
	fn(42)
}

How account kit work

1. client access token
-> you aren’t running your own servers
-> simpler to implement
-> long-lived token

2. authorization code (more secure)
-> all other cases
-> requires extra steps server-side
-> client never sees the token

repositories {
	jcenter()
}
allprojects {
	repositories {
		jcenter()
	}
}
dependencies {
	compile 'com.facebook.android:account-kit-sdk:4.+'
}

Post request

client -> data -> server

func performThisclosure(closure: (void) -> void){
	closure()
}
func justDoIt(it: (Void) -> Void){
	it()
}
justDo {
	print("print me now!")
}
var somethingToDo: (Void) -> Void = {}

func doItLater(it: @escaping (void) -> Void){
	somethingToDo = it
}

subdomain

an extension to a domain name used to organize resources together

https://api.themoviedb.org/3/authentication/token/new?api_key=ENTER_YOUR_API_KEY_HERE

extension AppDelegate {
	
	func tmdbURLFromParameters{_ paramters: [String:AnyObject], withPathExtension: String? = nil) -> URL {

		var components = URLComponents()
		components.scheme = Constants.TMDB.ApiScheme
		components.host = Constants.TMDB.ApiHost
		components.path = Constants.TMDB.ApiPath + (withPathExtension ?? "")
		components.queryItems = [URLQueryItem]()

		for (key, value) in parameters {
			let queryUtem = URLQueryItem(name: key, value: "\(value)")
			components.queryItems!.append(queryItem)
		}
		return components.url!
	}}
}
private func getRequestToken() {

    /* TASK: Get a request token, then store it (appDelegate.requestToken) and login with the token */

    /* 1. Set the parameters */
    let methodParameters = [
        Constants.TMDBParameterKeys.ApiKey: Constants.TMDBParameterValues.ApiKey
    ]

    /* 2/3. Build the URL, Configure the request */
    let request = URLRequest(url: appDelegate.tmdbURLFromParameters(methodParameters as [String:AnyObject], withPathExtension: "/authentication/token/new"))

    /* 4. Make the request */
    let task = appDelegate.sharedSession.dataTask(with: request) { (data, response, error) in

        // if an error occurs, print it and re-enable the UI
        func displayError(_ error: String) {
            print(error)
            performUIUpdatesOnMain {
                self.setUIEnabled(true)
                self.debugTextLabel.text = "Login Failed (Request Token)."
            }
        }

        /* GUARD: Was there an error? */
        guard (error == nil) else {
            displayError("There was an error with your request: \(error)")
            return
        }

        /* GUARD: Did we get a successful 2XX response? */
        guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 else {
            displayError("Your request returned a status code other than 2xx!")
            return
        }

        /* GUARD: Was there any data returned? */
        guard let data = data else {
            displayError("No data was returned by the request!")
            return
        }

        /* 5. Parse the data */
        let parsedResult: [String:AnyObject]!
        do {
            parsedResult = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! [String:AnyObject]
        } catch {
            displayError("Could not parse the data as JSON: '\(data)'")
            return
        }

        /* GUARD: Did TheMovieDB return an error? */
        if let _ = parsedResult[Constants.TMDBResponseKeys.StatusCode] as? Int {
            displayError("TheMovieDB returned an error. See the '\(Constants.TMDBResponseKeys.StatusCode)' and '\(Constants.TMDBResponseKeys.StatusMessage)' in \(parsedResult)")
            return
        }

        /* GUARD: Is the "request_token" key in parsedResult? */
        guard let requestToken = parsedResult[Constants.TMDBResponseKeys.RequestToken] as? String else {
            displayError("Cannot find key '\(Constants.TMDBResponseKeys.RequestToken)' in \(parsedResult)")
            return
        }

        /* 6. Use the data! */
        self.appDelegate.requestToken = requestToken
        self.loginWithToken(self.appDelegate.requestToken!)
    }

    /* 7. Start the request */
    task.resume()
}

Accessing User

Personal and Private == “User” Data
sometimes all the data is ‘user’ data

Anyone can access == “Anonymous” Data
(call a method using API key and arguments)

Authentication — ensuring someone’s identity (i.e. “we’ve confirmed this user is indeed Jarrod Parkes”)
Authorization — providing someone access to something (i.e. “this user is allowed to post ratings for movies”)

Which methods to use?
get a list of movies by genre? /genre/{$id$}/moview
get a list of our favorite movies? /account/{$id$}/favorite/movies
add or remove a movie from our favorites list? /account/{id}/favorite

Movie DB API
https://developers.themoviedb.org/3/getting-started

Getting strated
1. Partially implemented so we can focus on networking
2. Uses the AppDelegate like singleton
3. Each HTTP request is broken into 7 steps

Pieces of a URL

http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo

1.query, 2.hostname, 3.scheme, 4.path

https://api.flickr.com/service/rest?safe_search=1&extras=url_m&bbox=1.29,47.85,3.29,49.85&api_key=[YourApiKey]&method=flickr.photo.search&format=json&nojsoncallback=1

Swift equivalent for MIN and MAX macros
https://stackoverflow.com/questions/24186648/swift-equivalent-for-min-and-max-macros

NSURLSession, NSURLRequest, NSURLSessionDataTask

Make request -> Parse the JSON returned -> Determine # of pages of results -> Generate random # in that range -> Make a second request -> Get the random photo from random page of results

private func displayImageFromFlickrBySearch(_ methodParameters: [String: AnyObject], withPageNumber: Int){
	
	var methodParametersWithPageNumber = methodParameters
	methodParametersWithPageNumber[Constants.FlickrParmeterKeys.Page] = withPageNumber as AnyObject?
}

Search Method

48.85N, 2.29E
LatLon.net
48.85

NSURLQueryItem(name: “name”,value:”value”)
public var queryItems:[NSURLQueryItem]?

import Foundation

var components = URLComponents()
components.scheme = "https"
components.host = "api.flickr.com"
components.path = "/services/rest"
components.queryItems = [URLQueryItem]()

let queryItem1 = URLQueryItem(name: "method", value: "flickr.photo.search")
let queryItem2 = URLQueryItem(name: "api_key", value: "1234")
let queryItem3 = URLQueryItem(name: "text", value: "purple")

components.queryItems!.append(queryItem1)
components.queryItems!.append(queryItem1)
components.queryItems!.append(queryItem1)

print(components.url!)