DMfiend
DMfiend

Reputation: 195

Accessing swift dictionary members using AnyObject

I'm having trouble with understanding how to properly do unwrapping in Swift. Here is the situation:

I have these two classes:

class Alpha
{
  var val: Int

  init(x: Int)
  {
    val = x
  } 

  func doSomething() -> Int
  {
    // does stuff and returns an Int value
    return val
  }
}

and a second class which is a subclass of the first

class Beta: Alpha
{
  var str: [String] = []

  override init(x: Int)
  {
    super.init(x)
  }

  func doSomething() -> String
  {
    // does stuff and returns a String
    return str
  }
}

So far so good, these two classes work as expected. But now I want to create a dictionary to store several of both these class objects. So I've created a class to manage the dictionary and add items to it.

class Gamma
{
  var myDict: [String:AnyObject] = [:]

  func addAlphaToDict(key: String, val: Int)
  {
    self.myDict[key] = Alpha(x: val).self
  }

  func addBetaToDict(key: String, val: Int)
  {
    self.myDict[key] = Beta(x: val).self
  }
}

This also is working, but I think this could somehow be improved. The issue I'm having is now when I try to access values in the dictionary:

var foo = Gamma()

foo.addAlphaToDict(key: "blah", val: 45)
foo.addBetaToDict(key: "bluh", val: 23)

var result1 = (foo.myDict["blah"] as! Alpha).doSomething()

var result2 = (foo.myDict["bluh"] as! Beta).doSomething()

I find that the syntax here is very clunky and I feel like I'm doing it wrong, even though it works. I'm an experienced developer, but have only just started using Swift so I'm not really sure about certain things. Could someone with more Swift experience show me how to improve this code, or point me in the direction I should be going? Thanks!

Upvotes: 1

Views: 260

Answers (2)

Josh Homann
Josh Homann

Reputation: 16327

In swift when you want a heterogeneous type with a finite number of possibilities, prefer an enum with associated values to Any or AnyObject. You can then use a switch to recover the type in an exhaustive and type safe way.

import UIKit
import PlaygroundSupport

enum DictionaryValues {
    case integer(Int), string(String)
}

let dictionary: [String: DictionaryValues] = ["a": .integer(1), "b": .string("xyz")]

for (key, value) in dictionary {
    switch value {
    case .integer(let number):
        print("Key \(key) is a number: \(number)")
    case .string(let text):
        print("Key \(key) is text: \(text)")
    }
}

Upvotes: 1

Rakesha Shastri
Rakesha Shastri

Reputation: 11242

You can use Alpha instead of AnyObject as your dictionary value in this case. Just downcast it to Beta when needed. Using AnyObject or Any as the dictionary key should be avoided as much as possible.

However, i have to say that this approach is bad. You need to have a clearer logic to decide when the key will be Beta other than just relaying on knowing which key you are passing to the dictionary.

Upvotes: 2

Related Questions