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!)

Achievement Solution

var matchmakingIds: [Int] = []

for categoryDictionary in categoryDictionaries {
	
	if let title = categoryDictionary["title"] as? String, title == "Matchmaking"{


		guard let children = categoryDictionary["children"] as? [NSDictionary] else {
			print("Cannot find key 'children' in \(categoryDictionary)")
			return
		} 

		for child in children {
			guard let categoryId = child["categoryId"] as? Int else {
			 	print("Cannot find key 'categoryId' in \(child)")
			    return
			}
			matchmakingIds.append(categoryId)

		}
	}

}

JSON Example

{ 
  "first": "John",
  "last": "Smith",
  "age": 35,
  "employeed": true,
  "hobbies": [
    "fishing",
    "bowling",
    "programming"
  ],
  "relatives": {
    "mother": "Susan",
    "father": "Eric",
    "siblings": null 
  }
}

Here is a simple mapping JSON types to Swift types(JSON –> Swift)
null ==> nil
Number ==> Int, Float, Double
String ==> Bool
Array ==> [AnyObject]
Object ==> [String:AnyObject]

guard let arrayOfPhotoDictionaries = photosDictionary["photo"] as? [[String:AnyObject]] else {
	print("Cannot find key 'photo' in \(photosDictionary)")
	return
}
for (index, photo) in arrayOfPhotoDictionaries.enumerated(){
	print("\(index):\(photo)")
}
let rarities = ["Free", "Common"]

for rarity in rarities {
	numCostForRarityItemsDictionary[rarity] = 0
	sumCostForRarityDictionary[rarity] = 0
}

guard let rarityForCard = cardDictionary["rarity"] as? String else {
	print("Cannot find key 'rarityForCard' in \(cardDictionary)")
	return
}

numCostForRarityItemsDictionary[rarityForCard]! += 1
sumCostForRarityDictionary[rarityForCard]! += manaCost

guard let arrayOfBasicSetCardDictionaries = parsedHearthstoneJSON["Basic"] as? [[String:AnyObject]] else {
	print("cannot find key 'basic" in \(parsedHearthstoneJSON)")
	return
}

Parsing JSON

keyX, valueX: numbers, array, even dictionary

Parsing JSON
1. get the raw JSON data
2. parse the JSON data into a funcation object
3. grab the data from the foundation object

if let photosDictionary =
    parseResult[Constants.FlickrResponseKeys.Photos] as? [String:
    AnyObject],
    photoArray = photosDictonary[Constants.FlickrResponseKeys.Photo] as?
        [String:AnyObject]{

         let randomPhotoIndex = Int(ar:4random_uniform(UInt32(photoArray.count)))
        }
private func getImageFromFlickr(){
    
    let methodParameters = [
        Constants.FlickrParameterKeys.Method: Constants.FlickrParameterValues.GalleryPhotosMethod,
        Constants.FlickrParameterKeys.APIKey: Constants.FlickrParameterValues.APIKey,
        Constants.FlickrParameterKeys.GalleryID: Constants.FlickrParameterValues.GalleryID,
        Constants.FlickrParameterKeys.Extras: Constants.FlickrParameterValues.MediumURL,
        Constants.FlickrParameterKeys.Format: Constants.FlickrParameterValues.ResponseFormat,
        Constants.FlickrParameterKeys.NoJSONCallback: Constants.FlickrParameterValues.DisableJSONCallback   
    ]

    let session = URLSession.shared
    lel urlString = Constants.Flickr.APIBaseURL + escapedParameters(methodParameters as [String:AnyObject]) 
    let url = URL(string: urlString)!
    let request = URLRequest(url: url)

    let task = session.dataTask(with: request){ (data, response, error) in

        func displayError(_ error: String){
            print(error)
            print("URL at time of error: \(url)")
            performUIUpdatesOnMain{
                self.setUIEnabled(true)
            }

        guard(error == nil) else {
            displayError("There was an error with your request: \(error)")
            return
        }

        guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode
            displayError("Your request returned a status code other than 2xx!") 
            return       
        }

        guard let data = data else {
            displayError("No data was returned by the request!")
            return
        }

        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 let stat = parsedResult[Constants.FlickrResponseKeys.Status] as ? String, stat == Constants.FlickrResponseValues.OKStatus else {
            displayError("Cannot find keys '\(Constants.FlickrResponseKeys.Photos)'")
            return        
    }  

    let randomPhotoIndex = Int(arc4random_uniform(UInt32(photoArray.count)))
    let photoDictionary = photoArray[randomPhotoIndex] as [String:AnyObject]
    let photoIitle = photoDictionary[Constants.FlickrResponseKeys.Title]as? String
   
    guard let imageUrlString = photoDictionary[Constants.FlickrResponseKeys.MediumURL] as? String else {
            displayError("Cannot find key '\(Constants.FlickrResponseKeys.MediumURL)' in \(photoDictionary)")
            return
}

    let imageURL = URL(string: imageUrlString)
    if let imageData = try? Data(contentsOf: imageURL!){
        performUIUpdatesOnMain {
            self.setUIEnabled(true)
            self.photoImageView.image = UIImage(data: imageDAta)
            self.photoTitleLabel.text = photoTitle ?? "(Untitled)"
        }
    } else {
        displayError("Image does not exist at \(imageURL)")
    }

    task.resume()

Basics of Serialization

if let data = data {
	let parsedResult: AnyObject!
	do {
		parsedResult = try NSJSONSerialization.JSONObjectWithData(data, options: AllowFraments)
	} catch {
		displayError("could not parse the data as JSON: '\(data)'")
		return
	}
}

Making a request

let urlString = constant.Flickr.APIBaseURL + escapeParameters(methodParameters)
let url = NSURL(string: urlString)!
let request = NSURLRequest(URL: url)

let task = NSURLSession.sharedSession().dataTaskWithRequest(request){
	(data, response, error) in

	if error == nil {
		print(data)
	}
}

Escaping Parameters

private func escapedParameters(parameters: [String:]) -> String {
	if parameters.isEmpty {
		return ""
	} else {
		var keyValuePairs = [String]()

		for(key, value) in parameters {

			let stringVavlue "\(value)"

			let escapeValue = stringValue.
				stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())

			keyValuePairs.append(key + "=" + "\(escapedValue!)")
		}

		return "?\(keyValuePairs.joinWithSeparator("&"))"
	}

}
let someParameters = [
	"course": "networking",
	"hogehoge":"ios",
	"quiz":"escaping parameters"
]

print(escapedParameters(someParameters))

flickr API Method

flickr.galleries.getPhotos – to get a list of photos for a gallery
flickr.peoplegetPublicPhotos – to get a list of public photos for the given user
flickr.stats.getPhotoStas- to get the number of views, comment and favoites on a photo for a fiven date
flickr.urls.getUserPhotos- to get the url to a user’s photos

specifies the API
https://api.flickr.com/services/rest?method=flickr.galleries.getPhotos&api_key=hogehoge&gallery_id=hogehoge&extras=url_m&format=json&nojsoncallback=1&api_sig=hogehoge

import UIKit

class ViewController: UIViewController {
	
	@IBOutlet weak var photoImageView: UIImageView!
	@IBOutlet weak var photoTitleLabel: UILabel!
	@IBOutlet weak var grabImageButton: UIButton!

	@IBAction func grabNewImage(_ sender: AnyObject){
		setUIEnabled(false)
		getImageFromFlickr()
	}

	private func setUIEnabled(_ enabled: Bool){
		photoTitleLabel.isEnabled = enabled
		grabImageButton.isEnabled = enabled

		if enabled {
			grabImageButton.alpha = 1.0
		} else {
			grabImageButton.alpha = 0.5
		}

		private func getImageFromFlickr(){
		
		}
	}
}