Saml92
Saml92

Reputation: 91

Swift 3 ambiguous use of subscript only when debugging on device

So I'm making a small app to update some data on a website that I'm hosting. I've never written anything in swift 3 so it's all a bit confusing to me.

Right now I'm pulling a list of names from the site to use in a picker, for obvious reasons I will edit the url for the service I'm using but all the code should be understandable.

I have this code that works on the emulator which I've set up to be the same model as my phone(6s), it will work in the emulator but when I try and test it on my phone it errors with ambiguous use of subscript(I'll indicate the line in the code)

import UIKit

class ViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

@IBOutlet weak var playerTextPicker: UITextField!

var pickOption = [String]()
let picker = UIPickerView()

override func viewDidLoad() {
    super.viewDidLoad()
    getPlayerJson()
    picker.delegate = self
    picker.dataSource = self

    playerTextPicker.inputView = picker
}

public func numberOfComponents(in pickerView: UIPickerView) -> Int{
    return 1
}

public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
    return pickOption.count
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return pickOption[row]
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    playerTextPicker.text = pickOption[row]
    self.view.endEditing(false)
}

func getPlayerJson(){
    let players = [String]()
    let url = URL(string: "http://www.test.com/test.php")

    let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in

        if error != nil{
            print("Error")
        }
        else{
            if let myData = data{
                do{
                    let jsonResult = try JSONSerialization.jsonObject(with: myData, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject

                    var jsonElement: NSDictionary = NSDictionary()

                    for i in 0 ..< jsonResult.count
                    {

                        jsonElement = jsonResult[i] as! NSDictionary //ERRORS HERE


                        //the following insures none of the JsonElement values are nil through optional binding
                        if
                            let name = jsonElement["name"] as? String
                        {
                            self.pickOption.append(name)
                        }


                    }

                }catch{
                    //print error
                }
            }
        }
    }
    task.resume()
}
}

Upvotes: 0

Views: 687

Answers (2)

gnasher729
gnasher729

Reputation: 52592

When you use Swift, you should really try to use Swift code. Your code isn't Swift, it's Objective-C trying to pretend it is Swift.

The mutableContainers option is nonsense and just slows your code down (use it when you understand what it does and you need it). Use [] instead.

Since you are not handling the case that JSONSerialization throws, just use try?

Cast the result of JSONSerialization to as? [Any].

Looping through an array: for (item in array) Getting a dictionary and checking that it worked instead of crashing:

if let dict = item as? [AnyHashable, Any] {
}

Upvotes: 1

Code Different
Code Different

Reputation: 93181

I don't know how the simulator allowed you to do this, but this line:

let jsonResult = try JSONSerialization.jsonObject(with: myData, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject

A JSON object is either an array or a dictionary. AnyObject is ambiguous. If you are sure that it's an array, cast it to [AnyObject]:

let jsonResult = try JSONSerialization.jsonObject(with: myData, options: .mutableContainers) as! [AnyObject]

Upvotes: 1

Related Questions