I'm trying to create a function in a parent class that can be accessible to it's child classes. The issue I'm having is part of the function is referring to an init that needs to happen in the child class. I get an error:
Argument passed to call that takes no arguments
I'm not completely sure how to make the function available to it's child classes without copy and pasting it inside each child class.
Here is the parent class:
class JSONObject: NSObject {
static func updateResultsDictionary(urlExtension: String, completion:
@escaping (JSONObject?) -> Void) {
let nm = NetworkManager.sharedManager
_ = nm.getJSONData(urlExtension: urlExtension) {data in
guard let jsonDictionary = nm.parseJSONFromData(data), let
resultDictionaries = jsonDictionary["result"] as?
[[String : Any]] else {
completion(nil)
return
}
for resultsDictionary in resultDictionaries {
let jsonInfo = JSONObject(resultsDictionary: resultsDictionary)// Here is where the error "Argument passed to call that takes no arguments" happens
completion(jsonInfo)
}
}
}
}
This is a sample child class:
class AirBnBObject: JSONObject {
var airbnbUS: Int
var airbnbLocal: Int
init(airbnbUS: Int, airbnbLocal: Int){
self.airbnbUS = airbnbUS
self.airbnbLocal = airbnbLocal
}
init(resultsDictionary:[String: Any]){
guard let cost = resultsDictionary["cost"] as? [String: Any],
let airbnb = cost["airbnb_median"] as? [String : Any],
let usd = airbnb["USD"] as? Int,
let chf = airbnb["CHF"] as? Int
else {
airbnbUS = 0
airbnbLocal = 0
return
}
airbnbUS = usd
airbnbLocal = chf
}
}
I would move towards using a protocol instead of a class, that way you can design your JSONObject to require any classes that implement it to also implement init(resultsDictionary: [String:Any]). This allows you to write your updateResultsDictionary function in a protocol extension (which causes any implementing class to also inherit that function).
The protocol would look like this:
protocol JSONObject: class, NSObjectProtocol {
init(resultsDictionary: [String:Any])
}
extension JSONObject {
static func updateResultsDictionary<T: JSONObject>(urlExtension: String, completion:
@escaping (_ jsonObject: T?) -> Void) {
let nm = NetworkManager.sharedManager
_ = nm.getJSONData(urlExtension: urlExtension) {data in
guard let jsonDictionary = nm.parseJSONFromData(data),
let resultDictionaries = jsonDictionary["result"] as? [[String : Any]] else {
completion(nil)
return
}
for resultsDictionary in resultDictionaries {
let jsonInfo = T(resultsDictionary: resultsDictionary)
completion(jsonInfo)
}
}
}
}
The function needs to be generic in order to avoid the error you were seeing 'Protocol type cannot be instantiated'. Using class T which conforms to JSONObject rather than JSONObject itself fixes the error. (Note that in use T would be your conforming class, see below)
and any implementing class would look something like this:
class AirBnBObject: NSObject, JSONObject {
var airbnbUS: Int
var airbnbLocal: Int
init(airbnbUS: Int, airbnbLocal: Int){
self.airbnbUS = airbnbUS
self.airbnbLocal = airbnbLocal
}
required init(resultsDictionary:[String: Any]){
guard let cost = resultsDictionary["cost"] as? [String: Any],
let airbnb = cost["airbnb_median"] as? [String : Any],
let usd = airbnb["USD"] as? Int,
let chf = airbnb["CHF"] as? Int
else {
airbnbUS = 0
airbnbLocal = 0
return
}
airbnbUS = usd
airbnbLocal = chf
}
}
To use your extension function with this class you need to do it this way:
AirBnBObject.updateResultsDictionary(urlExtension: "") { (_ jsonObject: AirBnBObject?) -> Void in
print("update results dictionary")
}