3

I am still getting familiar with Swift, and I am having troubles with adding objects to an array at this moment. Also the array shouldn't have duplicates.

What I have so far -

A function that is called when user does a button click on a prototype cell. I am trying to achieve -

  1. Select button (and indicate with a checkmark that he selected/deselected the item)
  2. For each selected item, I have two values - bool status isActive and the selected item's subscriptionID
  3. When user selects the item, I need to add this selection as an object and further append this to an array.
  4. For that, I have subscriptionUpdateData: NSDictionary and my new empty array subscriptionsArray: [NSDictionary] = []

Full Function

 func subscriptionCell(cell: SubscriptionCell, didToggleSubscription subscription: Subscriptions) {

        var subscriptionsArray: [NSDictionary] = []
        var subscriptionUpdateData: NSDictionary = ["subscriptionID": 0, "isActive": false]

        if let matchingSubscription = subscriptionInformation?.filter({ $0.subscriptionID == subscription.subscriptionID }).first {

            matchingSubscription.isActive = !(matchingSubscription.isActive!)

            let subscriptionStatus = matchingSubscription.isActive
            let subscriptionStatusForId = matchingSubscription.subscriptionID

            subscriptionUpdateData = ["subscriptionID": subscriptionStatusForId!, "isActive": subscriptionStatus!]
            tableView.reloadData()
        }
        subscriptionsArray.append(subscriptionUpdateData)
        print("\(subscriptionsArray)")

    }

What is going on with above - I am able to select an item, form it as a dictionary, and add it to my array. :-) But whenever I select a different item in my list of items, it replaces the existing element in the array with the newly selected item. :-(

I am looking for something like below (without duplicates) which is an input to a REST endpoint -

    [{   "subscriptionID" : 1234, 
        "isActive" : true
    },
    {
        "subscriptionID" : 5678, 
        "isActive" : false
    },
    {
        "subscriptionID" : 3489, 
        "isActive" : true
    }]

Can someone look into where I am missing something? Or whether there is a better way I can do this?

5
  • 2
    Place your var subscriptionsArray: [NSDictionary] = [] outside of subscriptionCell method may be at instance level Commented Oct 24, 2016 at 16:03
  • the easiest way is to use predicates and filter your array to remove duplicates. Commented Oct 24, 2016 at 16:03
  • 1
    Why are you mixing Swift collection types and Cocoa collection types? Just use Swift collection types. In other words, don't use NSDictionary. Commented Oct 24, 2016 at 16:04
  • 1
    Add the isActive property to your data source model. An extra array is pretty cumbersome. And to get more familiar with Swift get rid of NSDictionary and use native Swift Dictionary or – still better – a custom class or struct. Commented Oct 24, 2016 at 16:06
  • Checkout the Set API to help you remove duplicate elements from a collection. Commented Oct 24, 2016 at 21:28

2 Answers 2

3

You must declare subscriptionsArray as global variable, try this code:

    var subscriptionsArray: [NSDictionary] = []
    func subscriptionCell(cell: SubscriptionCell, didToggleSubscription subscription: Subscriptions) {
        var subscriptionUpdateData: NSDictionary = ["subscriptionID": 0, "isActive": false]

        if let matchingSubscription = subscriptionInformation?.filter({ $0.subscriptionID == subscription.subscriptionID }).first {

            matchingSubscription.isActive = !(matchingSubscription.isActive!)

            let subscriptionStatus = matchingSubscription.isActive
            let subscriptionStatusForId = matchingSubscription.subscriptionID

            subscriptionUpdateData = ["subscriptionID": subscriptionStatusForId!, "isActive": subscriptionStatus!]
            tableView.reloadData()
        }
        subscriptionsArray.append(subscriptionUpdateData)
        print("\(subscriptionsArray)")

    }
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks! It works. But how do I get rid of duplication?
To avoid duplication, you should be using a Set rather than an Array. If the order matters, then there is also an NSOrderedSet.
You can just use the NSDictionary: var subscriptions: NSDictionary = [Int: Bool] =[:] and add data by code: subscriptions[subscriptionStatusForId] = subscriptionStatus
This isn't a global variable; it's an instance variable (or, in Swift terms, a property).
1

You can use swift dictionary to store those unique subscriptions by using their ids as keys:

id1: status1
id2: status2
...

Code sample:

var statusesDict = [Int: Bool?]()

func subscriptionToggled(subscription: Subscription) {
    if let matchingSubscription = subscriptionInformation?.filter({ $0.subscriptionID == subscription.subscriptionID }).first {
        let status = matchingSubscription.isActive
        let id = matchingSubscription.subscriptionID
        statusesDict[id] = status
    }
    //if you're using the same object from dataSource array, you dont need to look for it by filtering, just use the parameter object
}

Now, when you need to send the result to server just create an array from your dictionary:

func getSubscriptionsArray() -> [[String: Any]] {
    var result = [Dictionary<String, Any>]()
    for (id, status) in statusesDict.enumerated() {
        let subscriptionDict: [String: Any] = [
            "subscriptionID" : id,
            "isActive" : status
        ]
        result.append(subscriptionDict)
    }
    print("\(result)")
    return result
}

You should not send dictionary description as it is to server. First you should serialize it to JSON:

 let jsonData = try JSONSerialization.data(withJSONObject: array, options: [])
 let string = String(data: jsonData, encoding: String.Encoding.utf8)

For pretty printed json:

 let jsonData = try JSONSerialization.data(withJSONObject: array, options: JSONSerialization.WritingOptions.prettyPrinted)
 let string = String(data: jsonData, encoding: String.Encoding.utf8)

5 Comments

BTW, nobody uses the Dictionary<Key, Value> style of declaring dictionaries anymore. Just use [Key : Value].
@alexburtnik: Got it! But in subscriptionDict, it should be status.0 for "subscriptionID" and status.1 for "isActive" since id is the index in statusesDict.enumerated()
But the end result is [["isActive": 0, "subscriptionID": 1241], ["isActive": 1, "subscriptionID": 1237]], But I am looking for array of objects like [{"isActive": 0, "subscriptionID": 1241}, {"isActive": 1, "subscriptionID": 1237}]
@LohithKorupolu You should serialize it to json first, don't send dictionary directly.
@alexburtnik: Simple logic missed! thanks a lot!! My brain should be defragmented once :-|

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.