swift 5-error: «Ожидается расшифровка словаря» но нашел вместо этого массив. " - PullRequest
0 голосов
/ 18 марта 2020

Я новичок в быстром программировании, и я работаю над примером кода входа и регистрации, который нашел в Интернете. это сказало, это работает со всеми видами бэкэндов. поэтому я изменил его для работы с моим логином. php файлом. но я дошел только до сих пор ...

func handleResponse(for request: URLRequest,
                    completion: @escaping (Result<[User], Error>) -> Void) {

    let session = URLSession.shared

    let task = session.dataTask(with: request) { (data, response, error) in

        DispatchQueue.main.async {

            guard let unwrappedResponse = response as? HTTPURLResponse else {
                completion(.failure(NetworkingError.badResponse))
                return
            }

            print(unwrappedResponse.statusCode)

            switch unwrappedResponse.statusCode {

            case 200 ..< 300:
                print("success")

            default:
                print("failure")
            }

            if let unwrappedError = error {
                completion(.failure(unwrappedError))
                return
            }

            if let unwrappedData = data {

                do {
                    let json = try JSONSerialization.jsonObject(with: unwrappedData, options: [])
                    print(json)
                    if let users = try? JSONDecoder().decode([User].self, from: unwrappedData) {
                        completion(.success(users))
                    } else {
                        let errorResponse = try JSONDecoder().decode(ErrorResponse.self, from: unwrappedData)
                        completion(.failure(errorResponse))
                    }

                } catch {
                    completion(.failure(error))
                }
            }
        }
    }

    task.resume()
}

у меня есть эта функция запроса.

func request(endpoint: String,
             loginObject: Login,
             completion: @escaping (Result<User, Error>) -> Void) {

    guard let url = URL(string: baseUrl + endpoint) else {
        completion(.failure(NetworkingError.badUrl))
        return
    }

    var request = URLRequest(url: url)

    do {
        let loginData = try JSONEncoder().encode(loginObject)
        request.httpBody = loginData
        print(loginObject)
    } catch {
        completion(.failure(NetworkingError.badEncoding))
    }

    request.httpMethod = "POST"
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")

    handleResponse(for: request, completion: completion)
}

и затем я получил эту ошибку

typeMismatch(Swift.Dictionary<Swift.String, Any>, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary<String, Any> but found an array instead.", underlyingError: nil))

, поэтому я был поиск в Интернете, в основном здесь, что пошло не так. Я проверил код и выяснил, откуда возникла ошибка, и выяснил, что я должен изменить свой код на ...

        if let unwrappedData = data {

            do {
                let json = try JSONSerialization.jsonObject(with: unwrappedData, options: [])
                print(json)
                if let users = try? JSONDecoder().decode([User].self, from: unwrappedData) {
                    completion(.success(users))
                } else {
                    let errorResponse = try JSONDecoder().decode(ErrorResponse.self, from: unwrappedData)
                    completion(.failure(errorResponse))
                }

            } catch {
                completion(.failure(error))
            }
        }

, поэтому я подумал, что это правильное решение для моей проблемы. но, к сожалению, я получил еще одну ошибку после этого изменения ...

Member 'success' in 'Result<User, Error>' produces result of type 'Result<Success, Failure>', but context expects 'Result<User, Error>'

, и я больше не могу даже собрать и запустить код. Кто-нибудь может мне помочь? при необходимости я изменяю свой логин. php из массива в словарь.

это закрытие завершения?

enum MyResult<T, E: Error> {

    case success(T)
    case failure(E) }



func handleResponse(for request: URLRequest,
                        completion: @escaping (Result<User, Error>) -> Void) {
        ... }


enum NetworkingError: Error {
    case badUrl
    case badResponse
    case badEncoding }

ErrorResponse.swift

import Foundation

struct ErrorResponse: Decodable, LocalizedError {
    let reason: String

    var errorDescription: String? { return reason } }

Login.swift

import Foundation

struct Login: Encodable {
    let username: String
    let password: String }

User.swift

import Foundation

struct User: Decodable {
    let user_id: Int
    let username: String
    let password: String
    let firstname: String
    let surname: String
    let activated: Int
    let reg_time: String
}

print (json) ...

({
        activated = 1;
        firstname = Thomas;
        password = Maggie;
        "reg_time" = "0000-00-00 00:00:00";
        surname = Ghost;
        "user_id" = 2;
        username = "testuser";
    })

Теперь я почти вернулся в бизнес. я узнал, что мой user_id в mysql - это int (3), но swift 5 не воспринимает его как следует. когда я вынимаю let user_id: int, я наконец избавляюсь от последнего сообщения об ошибке. но теперь я могу войти в систему с помощью любого нажатия кнопки и любого пользователя и пароля, правильного или неправильного.

1 Ответ

0 голосов
/ 18 марта 2020

Я считаю, что проблема заключается в подписи вашего завершения завершения. Похоже, вы используете Swift.Result, но меняете типы c Success и Failure. Можете ли вы опубликовать функцию включения, где вы передаете закрытие завершения?

ОК, попробуйте изменить handleResponse на:

unc handleResponse(for request: URLRequest,
                    completion: @escaping (Result<[User], Error>) -> Void) {
    ... }

И убедитесь, что ErrorResponse реализует Error

...