Hi Brian,
I've been trying to implement a completionHandler to work with a pull down refresh, but it doesn't seem to refresh the list. Can you please review my code and let me know where I went wrong?
//
// NewController.swift
// GraphicsFactoryFeed
//
// Created by ROB GILLEN on 8/12/18.
// Copyright © 2018 ROB GILLEN. All rights reserved.
//
import UIKit
import SDWebImage
import SafariServices
class NewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
fileprivate let cellId = "cellId"
var courses = [Course]()
lazy var refresher: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.attributedTitle = NSAttributedString(string: "Updating New Images...")
refreshControl.addTarget(self, action: #selector(refreshImageData), for: .valueChanged)
//self.collectionView?.refreshControl = refreshControl
return refreshControl
}()
override func viewDidLoad() {
super.viewDidLoad()
setupCollectionView()
reloadCollection()
}
fileprivate func setupCollectionView() {
collectionView?.backgroundColor = .white
collectionView?.register(NewImageCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.refreshControl = refresher
}
struct Course: Decodable {
let id: Int
let title: String
let url: String
let link: String
let description: String
}
@objc private func refreshImageData() {
// Fetch Weather Data
print("updating image list")
reloadCollection()
let timer = DispatchTime.now() + .milliseconds(500)
DispatchQueue.main.asyncAfter(deadline: timer) {
self.refresher.endRefreshing()
}
}
func reloadCollection() {
fetchJSON { json, error in
}
}
fileprivate func fetchJSON(completionHandler:@escaping ([Course]?, Error?)->Void) {
let urlString = "https://www.graphicsfactory.com/json_two.json"
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url ) { (data, _, err) in
DispatchQueue.main.async {
if let err = err {
print("failed to get data:", err)
return
}
guard let data = data else { return }
do {
let decoder = JSONDecoder()
self.courses = try decoder.decode([Course].self, from: data)
//print(courses)
//print("refreshing images")
completionHandler(self.courses,nil)
self.collectionView?.reloadData()
} catch let jsonErr {
print("error:", jsonErr)
}
}
}.resume()
// Do any additional setup after loading the view, typically from a nib.
}
// MARK:- UICollectionView Delegate / Spacing Methods
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//return 5
return courses.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as? NewImageCell else {
fatalError("Wrong cell class dequeued")
}
self.navigationItem.title = "\(courses.count) New Images"
let course = courses[indexPath.row]
let url = URL(string: course.url)
//print (url)
cell.imageView.sd_setImage(with: url, completed: nil)
//cell.backgroundColor = .red
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let course = courses[indexPath.row]
let config = SFSafariViewController.Configuration()
config.entersReaderIfAvailable = false
if let url = URL(string: course.link) {
let vc = SFSafariViewController(url: url, configuration: config)
present(vc, animated: true)
}
// if UIApplication.shared.canOpenURL(url!) {
// UIApplication.shared.open(url!, options: [:], completionHandler: nil)
// }
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = (view.frame.width - 5 * 16) / 3
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 16
}
}