Reputation: 1953
My main class is an UITableViewController.
I'm fetching some JSON data with a ConnectionManager
class and parsing it with an ItemManager
class. The communication between classes is done using the NotificationCenter
. Whenever there is a response from ConnectionManager
it sends a notification to ItemManager
and then it parses it.
ConnectionManager posts notifications and ItemManager receives them correctly. I want to use the same approach to update my table view. The problem is with my main class. It doesn't receive the notifications from the ItemManager
when it is done parsing.
Some code:
class ConnectionManager {
private let URL = "http://foo.json"
private var response: Data?
init () {
getData()
}
func getData() {
let req = NSMutableURLRequest(url: NSURL(string: URL)! as URL)
req.httpMethod = "GET"
URLSession.shared.dataTask(with: req as URLRequest) { data, response, error in
if error != nil {
//HTTP request failed
NSLog(error?.localizedDescription ?? "Unknown Error")
NotificationCenter.default.post(name: Notification.Name(NotificationCenterKeys.NOK), object: nil)
} else {
//HTTP request succeeded
self.response = data
NotificationCenter.default.post(name: Notification.Name(NotificationCenterKeys.OK), object: nil)
}
}.resume()
}
}
class ItemManager {
private var cm: ConnectionManager
private var items = [Item]()
init() {
self.cm = ConnectionManager()
NotificationCenter.default.addObserver(self, selector: #selector(self.parseResponse), name: Notification.Name(NotificationCenterKeys.OK), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.noData), name: Notification.Name(NotificationCenterKeys.NOK), object: nil)
}
@objc private func noData() {
NSLog("No data to parse")
}
@objc private func parseResponse() {
do {
if let data = cm.getResponse() {
let items: NSDictionary = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.mutableContainers) as! NSDictionary
let rawItems = items["numbers"] as! [Int]
self.items = parseItems(rawItems: rawItems)
NotificationCenter.default.post(name: Notification.Name(NotificationCenterKeys.PARSED), object: nil)
}
} catch {
print("Error deserializing JSON: \(error)")
}
}
And finally my UITableViewController
:
class MainViewTableViewController: UITableViewController {
var items = [Item]()
var dataAvailable = false
var im = ItemManager()
var dataLabel = "Loading Data..."
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(self.updateTable), name: Notification.Name(NotificationCenterKeys.PARSED), object: nil)
setTable()
}
@objc func updateTable() {
if im.getItems()?.count != 0 {
items = im.getItems()!
dataAvailable = true
} else {
dataAvailable = false
dataLabel = "No Data Available"
}
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func setTable() {
title = "Test"
tableView.rowHeight = 40
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
var numOfSections = 0
if dataAvailable {
numOfSections = 4
return numOfSections
} else {
let noDataLabel: UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: tableView.bounds.size.width, height: tableView.bounds.size.height))
noDataLabel.text = dataLabel
noDataLabel.textColor = UIColor.black
noDataLabel.textAlignment = .center
tableView.backgroundView = noDataLabel
tableView.separatorStyle = .none
}
return numOfSections
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return getNumOfItemsPerSection(section: section)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TableViewCell
guard let sectionNumber = SectionNumber(rawValue: indexPath.section) else { return cell }
let elements = self.items.filter({ $0.sectionNumber == sectionNumber })
cell.nameLabel?.text = elements[indexPath.row].itemNumber?.description
if elements[indexPath.row].checkmark {
cell.accessoryType = .checkmark
} else { cell.accessoryType = .none }
return cell
}
func getNumOfItemsPerSection(section: Int) -> Int {
guard let sectionNumber = SectionNumber(rawValue: section) else { return 0 }
return self.items.filter({ $0.sectionNumber == sectionNumber }).count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section \(section + 1)"
}
}
Upvotes: 0
Views: 50
Reputation: 1953
Found the problem! I'm registering the observer after receiving the notification (ups)
class MainViewTableViewController: UITableViewController {
var items = [Item]()
var dataAvailable = false
var im: ItemManager? = nil
override func viewDidLoad() {
super.viewDidLoad()
setTable()
NotificationCenter.default.addObserver(self, selector: #selector(self.updateTable),
name: Notification.Name(NotificationCenterKeys.END), object: nil)
im = ItemManager()
}
...
Now works just fine :-)
Upvotes: 1