2
votes

My code was supporting Swift 3.3 before, now I'm upgrading it to Swift 4.1 using Xcode 9.3. It shows me the following error while trying to build my project.

Here is code for JSON parsing

    // MARK: Store JSON initializer

      convenience init?(withJSON json: JSON) {
        //json mapping 
        //This is of type [Character] after mapping
        let services = json["services"].arrayValue.flatMap({ $0 }).flatMap({ $0.1.stringValue }) //Convert response to 1D array and convert it to array if String

    }

Here is that init method which I'm trying to call

//Custom init method

  init(id: Int, storeNumber: String, title: String, location: Location, type: String, zip: String, parent: Int, city: String, services: [String], state: String, storePhone: [String], pharmacyPhone: [String], pharmacyFax: [String], workingHours: WorkingHoursString) {

    //field with error
    //here self.services is of type [String]
    self.services = services
  }

I'm using pod 'SwiftyJSON', '3.1.4' For Json parsing.

Error - Cannot convert value of type '[character]' to expected argument type '[String]'

enter image description here

/* JSON for services is as given

    "services":[
     [
     "Fresh Food"
     ]
    ]

*/
    print("Services are \(services)")
    Services are ["F", "r", "e", "s", "h", " ", "F", "o", "o", "d"]

What could be the simplest solution to fix this?

1
What does your JSON look like? - fulvio
I will have to build my code first, to see the JSON, as this code is of maintenance and we have just started working on this. But I will surely post JSON object if I get it somehow. - Pramod More
your error in the yellow bloc shows something different from the error the compiler threw ?? Error - Cannot convert value of type '[String]' to expected argument type '[character]' ...... and Cannot convert value of type '[Character]' to expected argument type '[String]' - PhillipJacobs
Simple solution will be : [String(services)]. But if you know proper structure of your JSON you will not fall in this situation. - Sharad Chauhan
Please show your json raw output in question. - TheTiger

1 Answers

2
votes

The same behavior can be observed in the following code:

let services: [[String: Any]?] = [
    ["service1": "service1-name"],
    ["service2": "service2-name"]
]

let result = services
    .flatMap({ $0 })
    .flatMap({ $0.1 as! String })
print(result)

I think this is caused by the multiple changes in String and Dictionary in Swift 4 (String becoming a Collection of characters for example). In the code above the first flatMap merges (flattens) the dictionaries into one dictionary and the second flatMap takes every value as a String and flattens them as a 2D Collection of Character.

I think you want something like this:

let result = services
    .compactMap { $0 } // remove nil dictionaries
    .flatMap { // take all dictionary values as strings and flatten them to an array
       $0.values.map { $0.stringValue }
    }
print(result)

This line gives an array of strings, expected results

let services = json["services"]
    .arrayValue
    .flatMap { $0.arrayValue }
    .map { $0.stringValue }