MainViewController 没有收到来自 NSNotificationCenter 的通知
MainViewController doesn't get notifications from NSNotificationCenter
我的主要 class 是一个 UITableViewController。
我正在使用 ConnectionManager
class 获取一些 JSON 数据并使用 ItemManager
class 解析它。 classes 之间的通信是使用 NotificationCenter
完成的。每当有来自 ConnectionManager
的响应时,它都会向 ItemManager
发送通知,然后对其进行解析。
ConnectionManager 发布通知并且 ItemManager 正确接收它们。我想使用相同的方法来更新我的 table 视图。问题出在我的主 class 上。解析完成后,它不会收到来自 ItemManager
的通知。
- ConnectionManager -> posts,ItemManager -> receives -- OK
- ItemManager -> posts,UITableViewController -> receives -- NOK
一些代码:
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)")
}
}
最后是我的 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({ [=11=].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({ [=11=].sectionNumber == sectionNumber }).count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section \(section + 1)"
}
}
找到问题了!
收到通知后注册观察员(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()
}
...
现在工作正常:-)
我的主要 class 是一个 UITableViewController。
我正在使用 ConnectionManager
class 获取一些 JSON 数据并使用 ItemManager
class 解析它。 classes 之间的通信是使用 NotificationCenter
完成的。每当有来自 ConnectionManager
的响应时,它都会向 ItemManager
发送通知,然后对其进行解析。
ConnectionManager 发布通知并且 ItemManager 正确接收它们。我想使用相同的方法来更新我的 table 视图。问题出在我的主 class 上。解析完成后,它不会收到来自 ItemManager
的通知。
- ConnectionManager -> posts,ItemManager -> receives -- OK
- ItemManager -> posts,UITableViewController -> receives -- NOK
一些代码:
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)")
}
}
最后是我的 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({ [=11=].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({ [=11=].sectionNumber == sectionNumber }).count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Section \(section + 1)"
}
}
找到问题了! 收到通知后注册观察员(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()
}
...
现在工作正常:-)