Skip to content

Instantly share code, notes, and snippets.

@stulevine
Created February 25, 2017 16:44
Show Gist options
  • Save stulevine/c5fbfdc1fc048a690a0da785e1fba609 to your computer and use it in GitHub Desktop.
Save stulevine/c5fbfdc1fc048a690a0da785e1fba609 to your computer and use it in GitHub Desktop.
Swift 3 - Playground showing KVC with dictionary from Quizlet API call
//: Playground - noun: a place where people can play
import UIKit
import Foundation
import PlaygroundSupport
class IndexCardView: UIView {
let topSpacing: CGFloat = 80.0
var lineColor = UIColor.clear
var lineWidth: CGFloat = 1.0
var topLineColor = UIColor.clear
var topLineWidth: CGFloat = 2.0
var withLines = true
var lineSpacing: CGFloat = 35.0
init(frame: CGRect,
lineSpacing: CGFloat = 35.0,
withLines: Bool = true,
backgroundColor: UIColor = UIColor(red: 0.9999, green: 0.9956, blue: 0.9749, alpha: 1.0),
lineColor: UIColor = UIColor(red: 0.3964, green: 0.6393, blue: 0.9988, alpha: 0.5),
topLineColor:UIColor = UIColor(red: 0.8338, green: 0.3722, blue: 0.3937, alpha: 0.5)) {
super.init(frame: frame)
self.backgroundColor = backgroundColor
self.topLineColor = topLineColor
self.lineColor = lineColor
self.withLines = withLines
self.lineSpacing = lineSpacing
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
// top red line
context?.beginPath()
context?.setStrokeColor(topLineColor.cgColor)
context?.setLineWidth(topLineWidth)
context?.move(to: CGPoint(x: 0.0, y: topSpacing))
context?.addLine(to: CGPoint(x: rect.width, y: topSpacing))
context?.strokePath()
// add blue lines if we want them
if withLines {
let deltaY: CGFloat = lineSpacing;
let numberOfLines: Int = Int((rect.height - topSpacing) / deltaY)
context?.beginPath()
context?.setStrokeColor(lineColor.cgColor)
context?.setLineWidth(lineWidth)
for i in 1...numberOfLines {
let Y = CGFloat(i) * deltaY;
context?.move(to: CGPoint(x: 0.0, y: topSpacing + Y))
context?.addLine(to: CGPoint(x: rect.width, y: topSpacing + Y))
}
context?.strokePath()
}
}
}
/* Example of JSON Quizlet Set Object
{
"id": 6009523,
"url": "http:\/\/quizlet.com\/6009523\/french-animals-30-flash-cards\/",
"title": "french animals 3.0",
"created_by": "catchdave",
"term_count": 13,
"created_date": 1310497102,
"modified_date": 1310497363,
"has_images": true,
"subjects": ["french", "animals"]
}
*/
class TableVC: UITableViewController {
enum JSONError: String, Error {
case NoData = "ERROR: no data"
case ConversionFailed = "ERROR: conversion from JSON failed"
}
let windowFrame = CGRect(x: 0.0, y: 0.0, width: 375, height: 667)
//let data = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen", "tenty"]
var data = [QuizletSet]()
let baseURL = "https://api.quizlet.com/2.0"
// you need this to make a call to the Quizlet API
// It's easy to sign up at https://quizlet.com/
let clientID = "client_id=<replace-with-your-quizlet-client-id>"
let searchSets = "/search/sets?per_page=25&q="
let getSet = "/sets"
override init(style: UITableViewStyle) {
super.init(style: style)
view.frame = windowFrame
view.backgroundColor = UIColor ( red: 0.5006, green: 0.8424, blue: 0.9991, alpha: 0.592982297687861 )
self.tableView.register(MyTableViewCell.self, forCellReuseIdentifier: "ri")
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
self.navigationItem.title = "Table Play"
searchQuizlet("algorithms")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "ri", for: indexPath)
cell.textLabel?.text = data[indexPath.row].title
cell.detailTextLabel?.text = String(indexPath.row)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cardVC = CardViewController(nibName: nil, bundle: nil)
cardVC.labelText = data[indexPath.row].url
cardVC.view
cardVC.qSet = data[indexPath.row]
self.navigationController?.pushViewController(cardVC, animated: true)
}
func searchQuizlet(_ searchText: String) {
let urlPath = baseURL + searchSets + searchText + "&\(clientID)"
print(urlPath)
guard let endpoint = URL(string: urlPath) else {
print("Error creating endpoint")
return
}
let request = URLRequest(url:endpoint)
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let dataTask = session.dataTask(with: request) { (data, response, error) in
do {
print("\(data)")
guard let data = data else {
throw JSONError.NoData
}
guard let json = try JSONSerialization.jsonObject(with: data, options: [.allowFragments]) as? NSDictionary else {
throw JSONError.ConversionFailed
}
print("\(json)")
var setData = [QuizletSet]()
var record: QuizletSet!
if let sets = json["sets"] as? [AnyObject] {
//print(json)
for qSet in sets {
if let setDict = qSet as? [String: AnyObject] {
record = QuizletSet(withJsonDict: setDict)
setData.append(record)
}
}
OperationQueue.main.addOperation {
self.data = setData
self.tableView.reloadData()
}
}
}
catch {
print("error: \(error.localizedDescription)")
}
}
dataTask.resume()
}
}
class QuizletSet: NSObject {
static let keyMap: [String: String] = ["id": "idNumber",
"url": "url",
"title": "title",
"created_by": "createdBy",
"term_count": "termCountNumber",
"created_date": "createdDate",
"modified_date": "modifiedDate",
"has_images": "hasImagesNumber",
"subjects": "subjects"]
var idNumber: NSNumber?
var id: Int? {
return idNumber?.intValue
}
var url: String?
var title: String?
var createdBy: String?
var termCountNumber: NSNumber?
var termCount: Int? {
return self.termCountNumber?.intValue
}
var createdDate: Date?
var modifiedDate: Date?
var hasImagesNumber: NSNumber = false
var hasImages: Bool {
return hasImagesNumber.boolValue
}
var subjects: [String]?
init(withJsonDict dict: [String: AnyObject?]) {
super.init()
for (key, value) in dict {
print("\(key) = \(value)")
if let mKey = QuizletSet.keyMap[key] {
if key.lowercased().contains("date") {
let date = Date(timeIntervalSince1970: Double(value as! Int))
self.setValue(date, forKey: mKey)
}
else {
self.setValue(value as Any, forKey: mKey)
}
}
}
}
}
class CardViewController: UIViewController {
var labelText: String?
var label: UILabel?
var qSet: QuizletSet?
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
let frame = UIApplication.shared.keyWindow?.frame
self.view = IndexCardView(frame: frame!)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(tappedCancelButton))
self.navigationItem.title = "A Card"
label = UILabel(frame: CGRect(x: 0, y: (self.view.frame.height-25)/2, width: self.view.frame.width, height: 50))
label!.textColor = UIColor.black
label!.textAlignment = .center
label!.numberOfLines = 0
self.view.addSubview(label!)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
label!.text = self.labelText
}
func tappedCancelButton(_ sender: UIBarButtonItem) {
self.navigationController?.popViewController(animated: true)
}
}
class MyTableViewCell: UITableViewCell {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: .subtitle, reuseIdentifier: reuseIdentifier)
}
}
let vc = TableVC(style: .plain)
let navVC = UINavigationController(rootViewController: vc)
PlaygroundPage.current.liveView = navVC
PlaygroundPage.current.needsIndefiniteExecution
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment