Saya baru mengenal pemrograman Swift dan saya sedang mengerjakan contoh xcode login dan registri yang saya temukan online. katanya, ini bekerja dengan semua jenis backend. jadi saya mengubahnya agar berfungsi dengan file login.php saya. tapi saya datang hanya sejauh ini ...

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()
}

Saya memiliki fungsi permintaan ini.

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)
}

Dan kemudian mendapatkan kesalahan ini

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

Jadi saya mencari online, kebanyakan di sini, apa yang salah. saya menguji kode dan menemukan dari mana kesalahan itu berasal dan saya menemukan, saya harus mengubah kode saya menjadi ...

        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))
            }
        }

Jadi saya pikir itu adalah perbaikan yang tepat untuk masalah saya. tapi sayangnya saya mendapat kesalahan lain setelah perubahan ini ...

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

Dan saya bahkan tidak dapat membuat dan menjalankan kode lagi. adakah yang bisa membantu saya? jika perlu saya mengubah login.php saya dari array ke kamus.

Apakah ini penutupan akhir?

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 }

Pengguna.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
}

Cetak (json) ...

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

Sekarang saya hampir kembali dalam bisnis. saya menemukan bahwa user_id saya di mysql adalah int (3) tetapi Swift 5 tidak menganggapnya sebagaimana mestinya. ketika saya mengeluarkan let user_id: int, saya akhirnya menghilangkan pesan kesalahan terakhir. tetapi sekarang saya dapat masuk dengan mengklik tombol apa saja dan pengguna dan kata sandi apa pun, apakah itu benar atau salah.

0
Didi Mike 18 Maret 2020, 05:55

1 menjawab

Jawaban Terbaik

Saya yakin masalahnya terletak pada tanda tangan penutupan penyelesaian Anda. Sepertinya Anda menggunakan Swift.Result tetapi memvariasikan tipe Sukses dan Kegagalan generik. Bisakah Anda memposting fungsi terlampir di mana Anda melewati penutupan penyelesaian?

Oke, coba ubah handleResponse menjadi:

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

Dan pastikan bahwa ErrorResponse mengimplementasikan Error

0
Brody Robertson 18 Maret 2020, 13:16