我有一个Singleton类:
class Session {
static let sharedInstance = Session()
private init() {}
// app properties
var token: String!
var promotions: JSON!
}
在网络类中,我有多个异步调用,我使用map
函数为每个网址启动:
let urls = [ "promotions": "http:..." ]
let results = urls.map { (k, url) in
self.getFromApi(url, params: ["token" : token]) { response in
guard response as? JSON != nil else { return }
Session.sharedInstance[k] = response
// the above should compile to Session.sharedInstance["promotions"] = response.
}
问题在于尝试通过下标设置sharedInstance的响应。我试图在Singleton上实现下标无济于事:
subscript(property: Any) -> Any {
get {
return Session.sharedInstance[property]
}
set(newValue) {
Session.sharedInstance[property] = newValue
}
}
我还尝试通过符合NSObject
并使用KVC
来放弃下标但是这也没有奏效&此外,我失去了所有类型的安全。
非常感谢任何帮助或建议。 提前谢谢。
答案 0 :(得分:1)
你可以让你的Singleton成为一个包类。您有一个包含JSON或属性的字典。其他一切都只是计算值。
class Session {
static let sharedInstance = Session()
private init() {}
// app properties
var token: String!
private var fetchedJSON : [String:Any] = [:]
var keys : [String] {
return Array(fetchedJSON.keys)
}
// handy to do downcasts in here
var promotions : JSON? {
get {
if let promotions = fetchedJSON["promotions"] as? JSON {
return promotions
} else {
return nil
}
}
set(value) {
fetchedJSON["prmotions"] = value
}
}
subscript(property: String) -> Any? {
get {
return fetchedJSON[property]
}
set(newValue) {
fetchedJSON[property] = newValue
}
}
}
或创建一个有限的KVC(这也可以通过Oliver Borchert的另一个答案中所述的反思来完成):
class Singleton {
var alpha : Any?
var beta : Any?
var delta : Any?
subscript(property: String) -> Any? {
get {
switch property {
case "alpha" : return self.alpha
case "beta" : return self.beta
case "delta" : return self.delta
default : return nil
}
}
set(newValue) {
switch property {
case "alpha" : self.alpha = newValue
case "beta" : self.beta = newValue
case "delta" : self.delta = newValue
default : return
}
}
}
}
答案 1 :(得分:1)
您可以使用反射。如果你有任何进一步的问题,我通常不会经常使用它,只需谷歌快速反思'。但要注意:反射可能看起来很好但速度很慢,只适用于NSObject
子类(我想,但随意试试)。它的工作原理如下:
subscript(property: String) -> Any {
get {
for i in 0..<reflect(self).count { // loop through all properties
if reflect(self)[i].0 == property { // find property with specified name
return reflect(self)[i].1.summary // return property's value
}
}
fatalError("no such property found")
} set(newValue) {
for i in 0..<reflect(self).count { // loop through all properties
if reflect(self)[i].0 == property { // find property with specified name
self.setValue(newValue, forKey: property) // not possible to do otherwise in Swift
return
}
}
}
}