0

I'm writing a getter/setter for a class property that uses a struct. This is ultimately parsed from JSON and converted back to JSON in order to store data in the cloud.

// struct:
public struct CompletedTask {
    var uuid: String!
    var amount: Float?
}

// array of completed tasks on the class:
public var completedTasks: [CompletedTask] {
    get {
        var getValue: [CompletedTask] = []
        if let _completedTasks = self["completedTasks"] as? [Dictionary<String, AnyObject>] {
            _completedTasks.forEach({
                getValue.append(CompletedTask(uuid: $0["uuid"], amount: nil))
            })
        }
        return getValue
    }
    set(value) {
        var setValue: [Dictionary<String, AnyObject>]
        value.forEach({
            if let amount = $0.amount where $0.amount != nil {
                setValue.append(["uuid": $0.uuid, "amount": amount])
            } else {
                setValue.append(["uuid": $0.uuid])
            }
        })
        self["completedTasks"] = setValue
    }
}

The setter (I think, although I cannot test) is working fine (it compiles, anyway). But the getter is throwing:

Cannot subscript a value of type '[String : AnyObject]' with an index of type 'String'

What's going on? I think this is a simple fix, but I've tried several different options and it's not working.

7
  • completedTasks it is an array so you need to use Int as index Commented Feb 16, 2016 at 4:52
  • Drat, see edit. Copy/paste fail. I'm doing a forEach and referencing $0; why wouldn't that work? Commented Feb 16, 2016 at 4:54
  • self["completedTasks"] = setValue self there will always be an array Commented Feb 16, 2016 at 4:54
  • Really not sure what you're getting at here. Even if I do this, I still have the same problem. Commented Feb 16, 2016 at 5:02
  • 1
    OH. I'm casting it to a dictionary not an array of dictionaries. [] vs [[]]. Commented Feb 16, 2016 at 5:03

3 Answers 3

1

Sorry to say this, but your code is completely wrong.

It's worthy to note that this code did not compile for me. I'm using Swift 2.0 and xcode 7.2. In addition, there are a few things I'd like to point out.

  1. You shouldn't be writing to your computed property. Look into stored properties instead. https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html#//apple_ref/doc/uid/TP40014097-CH14-ID259

  2. Unless you're extending a dictionary, you can't subscript properties of a class. To access a class's properties within a closure use self.completedTask.

  3. You can't simply cast a collection of a type you created to a collection of dictionaries.

  4. I don't actually see anything converted to JSON. I assume you did this somewhere else in the code.

Under the assumption that you wanted to created a computed property that saves a list of CompletedTasks as a Dictionary and returns a list of CompletedTask objects..

public struct CompletedTask {
    var uuid: String!
    var amount: Float?
}

private var tasks : [[String: AnyObject?]] = []

var completedTasks: [CompletedTask] {
    get {
        var _cT : [CompletedTask] = []

        tasks.forEach({
            _cT.append(CompletedTask(uuid: $0["uuid"] as! String, amount: $0["amount"] as? Float))
        })

        return _cT
    }
    set (value) {
        var _t : [[String: AnyObject?]] = []

        value.forEach({
            _t.append(["uuid": $0.uuid, "amount": $0.amount])
        })

        tasks = _t
    }
}
let task_1 = CompletedTask(uuid: "1", amount: nil)
let task_2 = CompletedTask(uuid: "2", amount: nil)
completedTasks = [task_1, task_2]
print("Completed Tasks \(completedTasks)")
Sign up to request clarification or add additional context in comments.

1 Comment

In fairness, there are a lot of assumptions in the snippet I posted. The class inherits from a super which already has the subscripting in place. Ultimately the solution was that I was not casting to String/Float as you have in your answer.
0

First things first,

if let amount = $0.amount where $0.amount != nil

is redundant, as the optional binding without the where clause guarantees that amount is not nil when the if let condition is satisfied.

As for that message, change AnyObject to Any, as String is a Struct and not a Class. AnyObject only works with classes.

More on Any vs AnyObject can be found here.

Comments

0

The error was simply due to the fact that I wasn't casting my types in the getter:

getValue.append(CompletedTask(uuid: $0["uuid"], amount: nil))

Should have been:

getValue.append(CompletedTask(uuid: $0["uuid"] as? String, amount: nil))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.