Swift error when trying to access Dictionary: `Could not find member 'subscript'` - swift

This won't compile:
I've tried a couple different things; different ways of declaring the Dictionary, changing its type to match the nested-ness of the data. I also tried explicitly saying my Any was a collection so it could be subscripted. No dice.
import UIKit
import Foundation
class CurrencyManager {
var response = Dictionary<String,Any>()
var symbols = []
struct Static {
static var token : dispatch_once_t = 0
static var instance : CurrencyManager?
}
class var shared: CurrencyManager {
dispatch_once(&Static.token) { Static.instance = CurrencyManager() }
return Static.instance!
}
init(){
assert(Static.instance == nil, "Singleton already initialized!")
getRates()
}
func defaultCurrency() -> String {
let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as String
let codesToCountries :Dictionary = [ "US":"USD" ]
if let localCurrency = codesToCountries[countryCode]{
return localCurrency
}
return "USD"
}
func updateBadgeCurrency() {
let chanCurr = defaultCurrency()
var currVal :Float = valueForCurrency(chanCurr, exchange: "Coinbase")!
UIApplication.sharedApplication().applicationIconBadgeNumber = Int(currVal)
}
func getRates() {
//Network code here
valueForCurrency("", exchange: "")
}
func valueForCurrency(currency :String, exchange :String) -> Float? {
return response["current_rates"][exchange][currency] as Float
}
}

Let's take a look at
response["current_rates"][exchange][currency]
response is declared as Dictionary<String,Any>(), so after the first subscript you try to call another two subscripts on an object of type Any.
Solution 1. Change the type of response to be a nested dictionary. Note that I added the question marks because anytime you access a dictionary item you get back an optional.
var response = Dictionary<String,Dictionary<String,Dictionary<String, Float>>>()
func valueForCurrency(currency :String, exchange :String) -> Float? {
return response["current_rates"]?[exchange]?[currency]
}
Solution 2. Cast each level to a Dictionary as you parse. Make sure to still check if optional values exist.
var response = Dictionary<String,Any>()
func valueForCurrency(currency :String, exchange :String) -> Float? {
let exchanges = response["current_rates"] as? Dictionary<String,Any>
let currencies = exchanges?[exchange] as? Dictionary<String,Any>
return currencies?[currency] as? Float
}

You can get nested dictionary data by following these steps:
let imageData: NSDictionary = userInfo["picture"]?["data"]? as NSDictionary
let profilePic = imageData["url"] as? String

func valueForCurrency(currency :String, exchange :String) -> Float? {
if let exchanges = response["current_rates"] as? Dictionary<String,Any> {
if let currencies = exchanges[exchange] as? Dictionary<String,Any> {
return currencies[currency] as? Float
}
}
return nil
}

response is declared as such:
var response = Dictionary<String,Any>()
So the compiler thinks response["current_rates"] will return an Any. Which may or may not be something that is subscript indexable.
You should be able to define you type with nested Dictionaries, 3 levels and eventually you get to a float. You also need to drill in with optional chaining since the dictionary may or may not have a value for that key, so it's subscript accessor returns an optional.
var response = Dictionary<String,Dictionary<String,Dictionary<String,Float>>>()
// ... populate dictionaries
println(response["current_rates"]?["a"]?["b"]) // The float

Related

how to get single variable name from struct

I have a core data framework to handle everything you can do with coredata to make it more cooperateable with codable protocol. Only thing i have left is to update the data. I store and fetch data by mirroring the models i send as a param in their functions. Hence i need the variable names in the models if i wish to only update 1 specific value in the model that i request.
public func updateObject(entityKey: Entities, primKey: String, newInformation: [String: Any]) {
let request = NSFetchRequest<NSFetchRequestResult>(entityName: entityKey.rawValue)
do {
request.predicate = NSPredicate.init(format: "\(entityKey.getPrimaryKey())==%#", primKey)
let fetchedResult = try delegate.context.fetch(request)
print(fetchedResult)
guard let results = fetchedResult as? [NSManagedObject],
results.count > 0 else {
return
}
let key = newInformation.keys.first!
results[0].setValue(newInformation[key],
forKey: key)
try delegate.context.save()
} catch let error {
print(error.localizedDescription)
}
}
As you can see the newInformation param contains the key and new value for the value that should be updated. However, i dont want to pass ("first": "newValue") i want to pass spots.first : "newValue"
So if i have a struct like this:
struct spots {
let first: String
let second: Int
}
How do i only get 1 name from this?
i've tried:
extension Int {
var name: String {
return String.init(describing: self)
let mirror = Mirror.init(reflecting: self)
return mirror.children.first!.label!
}
}
I wan to be able to say something similar to:
spots.first.name
But can't figure out how
Not sure that I understood question, but...what about this?
class Spots: NSObject {
#objc dynamic var first: String = ""
#objc dynamic var second: Int = 0
}
let object = Spots()
let dictionary: [String: Any] = [
#keyPath(Spots.first): "qwerty",
#keyPath(Spots.second): 123,
]
dictionary.forEach { key, value in
object.setValue(value, forKeyPath: key)
}
print(object.first)
print(object.second)
or you can try swift keypath:
struct Spots {
var first: String = ""
var second: Int = 0
}
var spots = Spots()
let second = \Spots.second
let first = \Spots.first
spots[keyPath: first] = "qwerty"
spots[keyPath: second] = 123
print(spots)
however there will be complex (or impossible) problem to solve if you will use dictionary:
let dictionary: [AnyKeyPath: Any] = [
first: "qwerty",
second: 123
]
you will need to cast AnyKeyPath back to WritableKeyPath<Root, Value> and this seems pretty complex (if possible at all).
for path in dictionary.keys {
print(type(of: path).rootType)
print(type(of: path).valueType)
if let writableKeyPath = path as? WritableKeyPath<Root, Value>, let value = value as? Value { //no idea how to cast this for all cases
spots[keyPath: writableKeyPath] = value
}
}

Dictionary of dictionaries in Swift

I'd like to build a dictionary of dictionaries. In Swift how do I declare a dictionary with a key of a String and the value of a dictionary of this same type? I need to be able to have potentially infinite nests. (Kind of like building a tree using nodes. Except it's not a tree, it's a dictionary.)
I tried using AnyObject, but get a conversion error:
var node1: Dictionary<String, AnyObject?> = ["foo" : nil]
var node2: Dictionary<String, AnyObject?> = ["bar" : node1] // ERROR: Cannot convert value of type 'Dictionary<String, AnyObject?>' (aka 'Dictionary<String, Optional<AnyObject>>') to expected dictionary value type 'Optional<AnyObject>'
Is there a type-safe way of doing this (i.e., not using AnyObject?)
You can achieve something like this with a nice API and type safety in swift by using a struct and an enumeration.
enum RecursiveDictValue<KeyType: Hashable, ValueType> {
case Value(ValueType)
case Dict(RecursiveDict<KeyType, ValueType>)
}
struct RecursiveDict<KeyType: Hashable, ValueType> {
typealias OwnType = RecursiveDict<KeyType, ValueType>
private var dict: [KeyType: RecursiveDictValue<KeyType, ValueType>]
init() {
dict = [:]
}
init(dict: [KeyType: RecursiveDictValue<KeyType, ValueType>]) {
self.dict = dict
}
// this ensures that we can safely chain subscripts
subscript(key: KeyType) -> OwnType {
get {
switch dict[key] {
case let .Dict(dict)?:
return dict
default:
return RecursiveDict<KeyType, ValueType>()
}
}
set(newValue) {
dict[key] = .Dict(newValue)
}
}
subscript(key: KeyType) -> ValueType? {
get {
switch dict[key] {
case let .Value(value)?:
return value
default:
return nil
}
}
set(newValue) {
if let newValue = newValue {
dict[key] = RecursiveDictValue<KeyType, ValueType>.Value(newValue)
} else {
dict[key] = nil
}
}
}
}
This works quite nicely (note that you need to help swift with the types though):
var dict = RecursiveDict<String, Int>(dict: ["value":.Value(1),
"dict":.Dict(RecursiveDict<String, Int>(dict: ["nestedValue": .Value(2)]))])
if let value: Int = dict["value"] {
print(value) // prints 1
}
if let value: Int = dict["dict"]["nestedValue"] {
print(value) // prints 2
}
It also fails as intended when you do stuff that can't work.
if let value: Int = dict["dict"] {
print(value) // is not executed
}
if let value: Int = dict["dict"]["nestedDict"]["nestedValue"] {
print(value) // is not executed
}
And you can even set values in nested dictionaries that haven't been created yet!:
dict["dict"]["nestedDict2"]["nestedValue"] = 3
if let value: Int = dict["dict"]["nestedDict2"]["nestedValue"] {
print(value) // prints 3
}
I was working with firebase, and i needed to achieve an structure similar to this:
["llave3": ["hola": "", "dos": ""], "llave1": ["hola": "", "dos": ""], "llave2": ["hola": "", "dos": ""]]
This is a nested dictionary, or a dictionary of dictionaries. I achieve this by simply doing this:
var array = ["llave1", "llave2","llave3"]
var dictOfDictionarys = [String : [String : String]] ()
for items in array {
dictOfDictionarys[items] = ["hola":"","dos":""]
}
Very less info.. and you mean infinite nested dictionaries? I dont think so..
func returnDict() -> Dictionary<String, AnyObject> {
return ["Got You" : returnDict()]
}
var x : Dictionary<String, AnyObject> = ["GotYou" : returnDict()]
Just saying, nothing better can happen to this other than a crash
this is a case of infinite recursion. When you have infinite dictionaries, it doesnt mean that it is going to run forever. It means that it is going to run till your device runs out of memory. A call to function returnDict, calls returnDict, which again calls returnDict and so on.
A recursion is basically adding a method onto the stack of pre-existing stack of methods in memory.. this can happen until the stack overflows. Hence, stackOverFlow
let node1: Dictionary<String, AnyObject!> = ["foo" : nil]
var node2 = ["bar" : node1]
Playground approves of it
The reason is that like in Objective-C values in the Dictionary type must be non-optional.
It's not very useful anyway because in Swift assigning a nil value to a key removes the key.
var node1: Dictionary<String, AnyObject> = ["foo" : "Hello"]
var node2: Dictionary<String, AnyObject> = ["bar" : node1]

Reflection in swift 2

I have a class User:
import UIKit
import ObjectMapper
class User: NSObject, CustomStringConvertible, Mappable {
var FirstName: NSString! ;
var LastName: NSString! ;
required init?(_ map: Map){
}
func mapping(map: Map) {
FirstName <- map["FirstName"]
LastName <- map["LastName"]
}
override var description:String {
var s:String=""
//USE REFLECTION TO GET NAME AND VALUE OF DATA MEMBERS
for var index=1; index<reflect(self).count; ++index {
s += (reflect(self)[index].0 + ": "+reflect(self)[index].1.summary+"\t")
}
return s
}
}
In swift 1.2, I was using reflect() method to get array of all the data members with their names and values.
Now, after I have updated to swift 2, I am getting the following error:
'reflect' is unavailable: call the 'Mirror(reflecting:)' initializer
With some trials, I was able to get the count of data members by this: Int(Mirror(reflecting: self).children.count), but still, I am unable to get the member name and its value.
I have looked into the following resources:
https://netguru.co/blog/reflection-swift
http://nshipster.com/mirrortype/
UPDATE
I have found the an answer here: https://stackoverflow.com/a/32846514/4959077. But this doesn't tell how to find out the type of reflected value. If the value is int and we parse it into String then it gives error.
You may access the reflected attribute "label" name, value and type as follows:
let mirror = Mirror(reflecting: SomeObject)
var dictionary = [String: Any]()
for child in mirror.children {
guard let key = child.label else { continue }
let value: Any = child.value
dictionary[key] = value
switch value {
case is Int: print("integer = \(anyValue)")
case is String: print("string = \(anyValue)")
default: print("other type = \(anyValue)")
}
switch value {
case let i as Int: print("• integer = \(i)")
case let s as String: print("• string = \(s)")
default: print("• other type = \(anyValue)")
}
if let i = value as? Int {
print("•• integer = \(i)")
}
}
Note: per the question followup, three approaches to determine the type of the reflected value are shown.
I have a solution that finds the name and type of a property given any class that inherits from NSObject.
I wrote a lengthy explanation on StackOverflow here, and my project is available here on Github,
In short you can do something like this (but really check out the code Github):
public class func getTypesOfProperties(inClass clazz: NSObject.Type) -> Dictionary<String, Any>? {
var count = UInt32()
guard let properties = class_copyPropertyList(clazz, &count) else { return nil }
var types: Dictionary<String, Any> = [:]
for i in 0..<Int(count) {
guard let property: objc_property_t = properties[i], let name = getNameOf(property: property) else { continue }
let type = getTypeOf(property: property)
types[name] = type
}
free(properties)
return types
}

Using reflection to set object properties without using setValue forKey

In Swift it's not possible use .setValue(..., forKey: ...)
nullable type fields like Int?
properties that have an enum as it's type
an Array of nullable objects like [MyObject?]
There is one workaround for this and that is by overriding the setValue forUndefinedKey method in the object itself.
Since I'm writing a general object mapper based on reflection. See EVReflection I would like to minimize this kind of manual mapping as much as possible.
Is there an other way to set those properties automatically?
The workaround can be found in a unit test in my library here
This is the code:
class WorkaroundsTests: XCTestCase {
func testWorkarounds() {
let json:String = "{\"nullableType\": 1,\"status\": 0, \"list\": [ {\"nullableType\": 2}, {\"nullableType\": 3}] }"
let status = Testobject(json: json)
XCTAssertTrue(status.nullableType == 1, "the nullableType should be 1")
XCTAssertTrue(status.status == .NotOK, "the status should be NotOK")
XCTAssertTrue(status.list.count == 2, "the list should have 2 items")
if status.list.count == 2 {
XCTAssertTrue(status.list[0]?.nullableType == 2, "the first item in the list should have nullableType 2")
XCTAssertTrue(status.list[1]?.nullableType == 3, "the second item in the list should have nullableType 3")
}
}
}
class Testobject: EVObject {
enum StatusType: Int {
case NotOK = 0
case OK
}
var nullableType: Int?
var status: StatusType = .OK
var list: [Testobject?] = []
override func setValue(value: AnyObject!, forUndefinedKey key: String) {
switch key {
case "nullableType":
nullableType = value as? Int
case "status":
if let rawValue = value as? Int {
status = StatusType(rawValue: rawValue)!
}
case "list":
if let list = value as? NSArray {
self.list = []
for item in list {
self.list.append(item as? Testobject)
}
}
default:
NSLog("---> setValue for key '\(key)' should be handled.")
}
}
}
I found a way around this when I was looking to solve a similar problem - that KVO can't set the value of a pure Swift protocol field. The protocol has to be marked #objc, which caused too much pain in my code base.
The workaround is to look up the Ivar using the objective C runtime, get the field offset, and set the value using a pointer.
This code works in a playground in Swift 2.2:
import Foundation
class MyClass
{
var myInt: Int?
}
let instance = MyClass()
// Look up the ivar, and it's offset
let ivar: Ivar = class_getInstanceVariable(instance.dynamicType, "myInt")
let fieldOffset = ivar_getOffset(ivar)
// Pointer arithmetic to get a pointer to the field
let pointerToInstance = unsafeAddressOf(instance)
let pointerToField = UnsafeMutablePointer<Int?>(pointerToInstance + fieldOffset)
// Set the value using the pointer
pointerToField.memory = 42
assert(instance.myInt == 42)
Notes:
This is probably pretty fragile, you really shouldn't use this.
But maybe it could live in a thoroughly tested and updated reflection library until Swift gets a proper reflection API.
It's not that far away from what Mirror does internally, see the code in Reflection.mm, around here: https://github.com/apple/swift/blob/swift-2.2-branch/stdlib/public/runtime/Reflection.mm#L719
The same technique applies to the other types that KVO rejects, but you need to be careful to use the right UnsafeMutablePointer type. Particularly with protocol vars, which are 40 or 16 bytes, unlike a simple class optional which is 8 bytes (64 bit). See Mike Ash on the topic of Swift memory layout: https://mikeash.com/pyblog/friday-qa-2014-08-01-exploring-swift-memory-layout-part-ii.html
Edit: There is now a framework called Runtime at https://github.com/wickwirew/Runtime which provides a pure Swift model of the Swift 4+ memory layout, allowing it to safely calculate the equivalent of ivar_getOffset without invoking the Obj C runtime. This allows setting properties like this:
let info = try typeInfo(of: User.self)
let property = try info.property(named: "username")
try property.set(value: "newUsername", on: &user)
This is probably a good way forward until the equivalent capability becomes part of Swift itself.
Swift 5
To set and get properties values with pure swift types you can use internal ReflectionMirror.swift approach with shared functions:
swift_reflectionMirror_recursiveCount
swift_reflectionMirror_recursiveChildMetadata
swift_reflectionMirror_recursiveChildOffset
The idea is to gain info about an each property of an object and then set a value to a needed one by its pointer offset.
There is example code with KeyValueCoding protocol for Swift that implements setValue(_ value: Any?, forKey key: String) method:
typealias NameFreeFunc = #convention(c) (UnsafePointer<CChar>?) -> Void
struct FieldReflectionMetadata {
let name: UnsafePointer<CChar>? = nil
let freeFunc: NameFreeFunc? = nil
let isStrong: Bool = false
let isVar: Bool = false
}
#_silgen_name("swift_reflectionMirror_recursiveCount")
fileprivate func swift_reflectionMirror_recursiveCount(_: Any.Type) -> Int
#_silgen_name("swift_reflectionMirror_recursiveChildMetadata")
fileprivate func swift_reflectionMirror_recursiveChildMetadata(
_: Any.Type
, index: Int
, fieldMetadata: UnsafeMutablePointer<FieldReflectionMetadata>
) -> Any.Type
#_silgen_name("swift_reflectionMirror_recursiveChildOffset")
fileprivate func swift_reflectionMirror_recursiveChildOffset(_: Any.Type, index: Int) -> Int
protocol Accessors {}
extension Accessors {
static func set(value: Any?, pointer: UnsafeMutableRawPointer) {
if let value = value as? Self {
pointer.assumingMemoryBound(to: self).pointee = value
}
}
}
struct ProtocolTypeContainer {
let type: Any.Type
let witnessTable = 0
var accessors: Accessors.Type {
unsafeBitCast(self, to: Accessors.Type.self)
}
}
protocol KeyValueCoding {
}
extension KeyValueCoding {
private mutating func withPointer<Result>(displayStyle: Mirror.DisplayStyle, _ body: (UnsafeMutableRawPointer) throws -> Result) throws -> Result {
switch displayStyle {
case .struct:
return try withUnsafePointer(to: &self) {
let pointer = UnsafeMutableRawPointer(mutating: $0)
return try body(pointer)
}
case .class:
return try withUnsafePointer(to: &self) {
try $0.withMemoryRebound(to: UnsafeMutableRawPointer.self, capacity: 1) {
try body($0.pointee)
}
}
default:
fatalError("Unsupported type")
}
}
public mutating func setValue(_ value: Any?, forKey key: String) {
let mirror = Mirror(reflecting: self)
guard let displayStyle = mirror.displayStyle
, displayStyle == .class || displayStyle == .struct
else {
return
}
let type = type(of: self)
let count = swift_reflectionMirror_recursiveCount(type)
for i in 0..<count {
var field = FieldReflectionMetadata()
let childType = swift_reflectionMirror_recursiveChildMetadata(type, index: i, fieldMetadata: &field)
defer { field.freeFunc?(field.name) }
guard let name = field.name.flatMap({ String(validatingUTF8: $0) }),
name == key
else {
continue
}
let clildOffset = swift_reflectionMirror_recursiveChildOffset(type, index: i)
try? withPointer(displayStyle: displayStyle) { pointer in
let valuePointer = pointer.advanced(by: clildOffset)
let container = ProtocolTypeContainer(type: childType)
container.accessors.set(value: value, pointer: valuePointer)
}
break
}
}
}
This approach works with both class and struct and supports optional, enum and inherited(for classes) properties:
// Class
enum UserType {
case admin
case guest
case none
}
class User: KeyValueCoding {
let id = 0
let name = "John"
let birthday: Date? = nil
let type: UserType = .none
}
var user = User()
user.setValue(12345, forKey: "id")
user.setValue("Bob", forKey: "name")
user.setValue(Date(), forKey: "birthday")
user.setValue(UserType.admin, forKey: "type")
print(user.id, user.name, user.birthday!, user.type)
// Outputs: 12345 Bob 2022-04-22 10:41:10 +0000 admin
// Struct
struct Book: KeyValueCoding {
let id = 0
let title = "Swift"
let info: String? = nil
}
var book = Book()
book.setValue(56789, forKey: "id")
book.setValue("ObjC", forKey: "title")
book.setValue("Development", forKey: "info")
print(book.id, book.title, book.info!)
// Outputs: 56789 ObjC Development
if you are afraid to use #_silgen_name for shared functions you can access to it dynamically with dlsym e.g.: dlsym(RTLD_DEFAULT, "swift_reflectionMirror_recursiveCount") etc.
UPDATE
There is a swift package (https://github.com/ikhvorost/KeyValueCoding) with full implementation of KeyValueCoding protocol for pure Swift and it supports: get/set values to any property by a key, subscript, get a metadata type, list of properties and more.
Unfortunately, this is impossible to do in Swift.
KVC is an Objective-C thing. Pure Swift optionals (combination of Int and Optional) do not work with KVC. The best thing to do with Int? would be to replace with NSNumber? and KVC will work. This is because NSNumber is still an Objective-C class. This is a sad limitation of the type system.
For your enums though, there is still hope. This will not, however, reduce the amount of coding that you would have to do, but it is much cleaner and at its best, mimics the KVC.
Create a protocol called Settable
protocol Settable {
mutating func setValue(value:String)
}
Have your enum confirm to the protocol
enum Types : Settable {
case FirstType, SecondType, ThirdType
mutating func setValue(value: String) {
if value == ".FirstType" {
self = .FirstType
} else if value == ".SecondType" {
self = .SecondType
} else if value == ".ThirdType" {
self = .ThirdType
} else {
fatalError("The value \(value) is not settable to this enum")
}
}
}
Create a method: setEnumValue(value:value, forKey key:Any)
setEnumValue(value:String forKey key:Any) {
if key == "types" {
self.types.setValue(value)
} else {
fatalError("No variable found with name \(key)")
}
}
You can now call self.setEnumValue(".FirstType",forKey:"types")

How to get selector name as an attribute on an object in Swift?

When working with rest JSON-APIs its convenient to keep usage of an attribute consistent throught the app and when calling the server
For this example:
class Picture: NSManagedObject {
#NSManaged var copyright: String
#NSManaged var likes: NSNumber
}
func postToServer() {
let newPicture = Picture(copyright: "haaakon", likes:433)
let arguments = #{
newPicture.copyright.selectorName : newPicture.copyright,
newPicture.likes.selectorName : newPicture.likes
}
println(arguments)
}
println should give this output:
{ "copyright": "haaakon", "likes": "433" }
How to go about when creating an extension (or other solution) on a given attribute that returns basically the same as:
NSStringFromSelector(Selector(newPicture.copyright)) // returns "copyright"
newPicture.copyright.selectorName // returns "copyright"
Try this:
extension Picture{
func dictionary() -> Dictionary<String, AnyObject> {
var outCount: CUnsignedInt = 0
let properties: UnsafeMutablePointer<objc_property_t> = class_copyPropertyList(self.dynamicType, &outCount)
var result: Dictionary<String, AnyObject> = Dictionary()
for var i = 0; i < Int(outCount); i++ {
var property : NSString! = NSString(CString: property_getName(properties[i]), encoding: NSUTF8StringEncoding)
result[property] = self.valueForKey(property)
}
return result
}
}