Can somebody help convert URLSession from Swift to Kotlin

Viewed 400

I want to make Multiplatform Weather App with Kotlin. And I also want get weather data separate for Android and iOS in common module.

With Android I haven't any problem, but with iOS part I have. I want to use Foundation framework to get and serialise data with URLSession. But it doesn't work.

Here is my Weather Model.

    package com.example.weatherappversion3.shared

    data class WeatherData (
        val cod: String,
        val message: Long,
        val cnt: Long,
        val list: List<ListElement>,
        val city: City
    )
    
    data class City (
        val id: Long,
        val name: String,
        val coord: Coord,
        val country: String,
        val population: Long,
        val timezone: Long,
        val sunrise: Long,
        val sunset: Long
    )
    
    data class Coord (
        val lat: Double,
        val lon: Double
    )
    
    data class ListElement (
        val dt: Long,
        val main: MainClass,
        val weather: List<Weather>,
        val clouds: Clouds,
        val wind: Wind,
        val visibility: Long,
        val pop: Double,
        val sys: Sys,
        val dtTxt: String,
        val snow: Rain? = null,
        val rain: Rain? = null
    )
    
    data class Clouds (
        val all: Long
    )
    
    data class MainClass (
        val temp: Double,
        val feelsLike: Double,
        val temp_min: Double,
        val temp_max: Double,
        val pressure: Long,
        val seaLevel: Long,
        val grndLevel: Long,
        val humidity: Long,
        val tempKf: Double
    )
    
    data class Rain (
        val the3H: Double
    )
    
    data class Sys (
        val pod: Pod
    )
    
    enum class Pod {
        D,
        N
    }
    
    data class Weather (
        val id: Long,
        val main: MainEnum,
        val description: String,
        val icon: String
    )
    
    enum class MainEnum {
        Clear,
        Clouds,
        Rain,
        Snow
    }
    
    data class Wind (
        val speed: Double,
        val deg: Long,
        val gust: Double
    )

And here is my request:

    package com.example.weatherappversion3.shared

    import com.example.weatherappversion3.shared.constants.Constants
    //import cocoapods.Alamofire.*
    import platform.Foundation.*
    import platform.darwin.NSObject
    
    //import SwiftyJSON
    
    actual class WeatherManager {

    actual var weatherData: WeatherData? = null
    var data = NSData()
    //https://api.openweathermap.org/data/2.5/forecast?appid=e83bce43f40758140ef6927fda5cfc85&units=metric&lat=48.51320000&lon=32.25970000
    var url = "https://api.openweathermap.org/data/2.5/forecast?appid=${Constants().AppId}&units=${Constants().units}&lat=${Constants().lat}&lon=${Constants().lon}"
    actual fun getWeatherForecastFor(updateUI: ()->Unit) {
        println("Start request for iOS")
        asyncRequest(url)
        updateUI()
    }

    fun asyncRequest(url: String) {

        val delegate = object : NSObject(), NSURLSessionDataDelegateProtocol {

            override fun URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData: NSData) {
                data = didReceiveData
            }

            override fun URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError: NSError?) {
                val response = task.response
                if (response == null || (response as NSHTTPURLResponse).statusCode.toInt() != 200) {
                    return
                }

                if (didCompleteWithError != null) {
                    return
                }

            }
        }

        val session = NSURLSession.sessionWithConfiguration(
            NSURLSessionConfiguration.defaultSessionConfiguration(),
            delegate,
            delegateQueue = NSOperationQueue.mainQueue()
        )

        session.dataTaskWithURL(NSURL(string = url)).resume()
    }

    actual fun getWeatherForecastForSpecialCity(city: String) {

    }

}
2 Answers

Kotlinx serialization is currently the recommended way of doing multiplatform serialization, it supports js, native and jvm targets

Here you can see an example of kotlinx serialization

In pure iOS, you would use the Codable protocol on your data, or manually decode using the JSONDecoder class from Foundation framework.

The Kotlin equivalent is Gson. There is probably other solutions.

Edited : Yes, there is other solution, see Kotlinx ( thanks to @joffrey for his comment ) - https://github.com/Kotlin/kotlinx.coroutines

    data class WeatherData (
        @SerializedName("cod_key")  // Optional field name
        val cod: String,
        val message: Long,
        val cnt: Long,
        val list: List<ListElement>,
        val city: City
    )

    didReceiveData() {
        val weather = Gson().fromJson<WeatherData>(data, WeatherData::class.java)
    }

https://github.com/google/gson

Related