In my Firebase project I'm trying to apply Model View Controller pattern, so I separated the controller and the class that handles firebase requests. I get this exception
exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance
I'm trying to get news items from the database. Here is the model
class NewsItem: NSObject{
var title: String?
var detail: String?
var photoUrl: String?
var timestamp: String?
}
Here is the firebase handler class
protocol NewsController: class {
func fetchedNews(_ newsItem: NewsItem)
}
class FirebaseHandler {
private static let _instance = FirebaseHandler()
static var Instance: FirebaseHandler{
return _instance
}
weak var newsControllerDelegate: NewsController?
func fetchNews() {
References.Instance.newsRef.observe(.childAdded) {
(snapshot: DataSnapshot) in
if let child = snapshot.value as? [String: AnyObject]{
let newsItem = NewsItem()
print("CHILD: \n\n\n\n\(child)\n\n\n")
newsItem.setValuesForKeys(child)
DispatchQueue.main.async {
self.newsControllerDelegate?.fetchedNews(newsItem)
}
}
}
}
}
I can get the child values printed fine, but the problem is when I call the protocol delegate method.
Here are some portions of the table view controller class where I adopt the NewsController
protocol:
FirebaseHandler.Instance.newsControllerDelegate = self
FirebaseHandler.Instance.fetchNews()
Then I implement the method:
func fetchedNews(_ newsItem: NewsItem) {
print("Item:\n\n\n\(newsItem)\n\n\n")
self.newsItems.append(newsItem)
self.tableView.reloadData()
}
The newsItem isn't printed since the error occurs before this method is called I guess. Any suggestions are appreciated.
From the reported NSNumber
related error, I would guess your timestamp
property is actually stored as an integer in Firebase (and not as a string). If this is the case, try changing it to:
var timestamp: Int = 0
To understand why we can't use Int?
(or even Int!
) above please see this answer as well.
Also: you don't need that DispatchQueue.main.async
wrapper in your observer code. All database callbacks are already called on the main thread by Firebase ;)