Reputation: 20808
I have a custom collection that can receive values of any type and converts them to strings. For example:
collection["key"] = 10
let value = collection["key"] // value is a String
Is there a way to do this? I tried implementing two subscript methods but Swift doesn't support write-only subscripts.
subscript(key: String) -> String {
get { ... }
}
// Doesn't compile
subscript(key: String) -> AnyObject {
set { ... }
}
Upvotes: 0
Views: 911
Reputation: 469
I was facing a similar problem here and I solved it using a generic type for my variable and returning the type I want on its getter. You can try doing something like this:
class StorageClass {
private var _value: String?
public var value: Any? {
set {
if let num = newValue as? Int {
self._value = String(format: "%d",num)
}
}
get {
return self._value
}
}
}
By doing this, it is possible to do something like:
var storage = StorageClass()
storage.value = 10 /* setting value as an Integer */
let aString = storage.value as! String /* receiving a String value back */
Upvotes: 0
Reputation: 535586
You can use two different subscript
implementations and disable the getter for one of them:
subscript(key: String) -> String {
get { return "howdy" } // put real implementation here
}
subscript(key: String) -> AnyObject {
get { fatalError("Oooops") }
set { }
}
However, this still leaves open the question of how to distinguish between these two subscript
calls in context. It would be better to give them different signatures through their external parameter names:
subscript(key: String) -> String {
get { return "howdy" } // put real implementation here
}
subscript(# any: String) -> AnyObject {
get { fatalError("Oooops") }
set { }
}
And here's how to use it:
let m = MyClass()
m[any:"thing"] = 1
println(m["thing"]) // "1", presumably
Upvotes: 2
Reputation: 91
You could also define your own type and make it conform to the IntegerLiteralConvertible
and the StringLiteralConvertible
protocols.
Technically you could also write an extension for String to make it conform to IntegerLiteralConvertible
but that might get confusing, since it will be available in your entire project.
Upvotes: 0
Reputation: 70185
Define subscript to return AnyObject
(or Any
as needed) and at the point you use the getter cast the result to String
. You may already need to deal with subscript
returning an optional so the coercion is just all part of extracting your desired value.
if let value = collection["key"] as String { ... }
else {...}
Upvotes: 0