2

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?

Pramod More
  • 1,220
  • 2
  • 22
  • 51
  • What does your JSON look like? – gotnull Jun 08 '18 at 06:15
  • 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 Jun 08 '18 at 06:17
  • 1
    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 Jun 08 '18 at 06:19
  • Simple solution will be : [String(services)]. But if you know proper structure of your JSON you will not fall in this situation. – Sharad Chauhan Jun 08 '18 at 06:20
  • Oh extremely sorry for the mistake, and thanks for your strong observation. Corrected it. @PhillipJacobs – Pramod More Jun 08 '18 at 06:22
  • 1
    Please show your json raw output in question. – TheTiger Jun 08 '18 at 06:28
  • "services":[ [ "Drive-Thru Pharmacy", "Red Box" ] ] //The services object is as follows in JSON – Pramod More Jun 11 '18 at 05:44
  • So I think, expected is an array of strings, but it is producing an array of characters. – Pramod More Jun 11 '18 at 05:57

1 Answers1

2

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 }
Sulthan
  • 128,090
  • 22
  • 218
  • 270