I was able to get the JSON data to show in console initially but later in the chapter when it has me parse the data I keep getting an error instead of the photo count that it’s supposed to show. Code below. Any ideas what I’ve done wrong?
This is my FlickrAPI.swift file:
import Foundation
enum FlickrError: Error {
case invalidJSONData
}
enum Method: String {
case interestingPhotos = “flickr.interestingness.getList”
}
struct FlickrAPI {
private static let baseURLString = "https://api.flickr.com/services/rest"
private static let apiKey = "a6d819499131071f158fd740860a5a88"
private static let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return formatter
}()
private static func flickrURL(method: Method, parameters: [String:String]?) -> URL {
var components = URLComponents(string: baseURLString)!
var queryItems = [URLQueryItem]()
let baseParams = [
"method": method.rawValue,
"format": "json",
"nojsoncallback": "1",
"api_key": apiKey
]
for (key, value) in baseParams {
let item = URLQueryItem(name: key, value: value)
queryItems.append(item)
}
if let additionalParams = parameters {
for (key, value) in additionalParams {
let item = URLQueryItem(name: key, value: value)
queryItems.append(item)
}
}
components.queryItems = queryItems
return components.url!
}
private static func photo(fromJSON json: [String : Any]) -> Photo? {
guard
let photoID = json["id"] as? String,
let title = json["title"] as? String,
let dateString = json["dateTaken"] as? String,
let photoURLString = json["url_h"] as? String,
let url = URL(string: photoURLString),
let dateTaken = dateFormatter.date(from: dateString) else {
//don't have enough information to construct a photo
return nil
}
return Photo(title: title, photoID: photoID, remoteURL: url, dateTaken: dateTaken)
}
static var interestingPhotosURL: URL {
return flickrURL(method: .interestingPhotos, parameters: ["extra": "url_h,date_taken"])
}
static func photos(fromJSON data: Data) -> PhotosResult {
do {
let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
guard
let jsonDictionary = jsonObject as? [AnyHashable:Any],
let photos = jsonDictionary["photos"] as? [String:Any],
let photosArray = photos["photo"] as? [[String:Any]] else {
//the json strucutre doesn't match our expectations
return .failure(FlickrError.invalidJSONData)
}
var finalPhotos = [Photo]()
for photoJSON in photosArray {
if let photo = photo(fromJSON: photoJSON) {
finalPhotos.append(photo)
}
}
if finalPhotos.isEmpty && !photosArray.isEmpty {
//we weren't able to parse any of the photos
//maybe the json format for the photos has changed
return .failure(FlickrError.invalidJSONData)
}
return .success(finalPhotos)
} catch let error {
return .failure(error)
}
}
}