Search code examples
swiftforeachbase64decodeambiguous

Swift 4: Type of expression is ambiguous without more context inside loop


I have a question:

I'm retrieving a long string made of some base 64 strings attached together with ";" separating each of them inside said string.

Here's my code:

   if(item.photo != "null"){
            let b64fullstring = item.photo
            if(b64fullstring!.contains(";")){
                let photos = b64fullstring!.split(separator: ";")
                
                for pic in photos{
                    let base64encodedstring = pic
                    let decodedData = Data(base64Encoded: base64encodedstring!, options: Data.Base64DecodingOptions.ignoreUnknownCharacters)!
                    let decodedString = String(data: decodedData, encoding: .utf8)!
                    print(pic)
                }
            }
        
        
        } 

Its gives me the following error on the "data" function; Type of expression is ambiguous without more context I really don't get it. When working on a single string, it works perfectly fine. But when using a loop, it gives this message for some reason.

Thank you for taking some of your time for helping me.


Solution

  • Swift errors are not very helpful. The problem there is that split method returns an array of substrings:

    func split(separator: Character, maxSplits: Int = Int.max, omittingEmptySubsequences: Bool = true) -> [Substring]
    

    And the Data initializer expects a String:

    init?(base64Encoded base64String: String, options: Data.Base64DecodingOptions = [])
    

    You just need to initialize a new string from your substring:

    if let photos = b64fullstring?.split(separator: ";") {
        for pic in photos {
            if let decodedData = Data(base64Encoded: String(pic), options: .ignoreUnknownCharacters) {
                if let decodedString = String(data: decodedData, encoding: .utf8) {
                    print(pic)
                }
            }
        }
    }
    

    Another option is to use components(separatedBy:) method which returns an array of strings instead of substrings:

    func components<T>(separatedBy separator: T) -> [String] where T : StringProtocol
    

    if let photos = b64fullstring?.components(separatedBy: ";") {
        for pic in photos {
            if let decodedData = Data(base64Encoded: pic, options: .ignoreUnknownCharacters) {
                if let decodedString = String(data: decodedData, encoding: .utf8) {
                    print(pic)
                }
            }
        }
    }