[Swift, a must-see for fledgling! ] Let's understand the implementation of communication processing of WebAPI

The implementation that beginners stumble upon is generally fixed. ** ・ Delegate ·closure ・ Communication ・ Error handling ·architecture** Isn't there a lot of beginners who get "?" Around here? And all of them are very important for development.

Here, I would like to make the content to understand the processing of API communication. I omit the explanations that are written in every article.

If you want to understand Delegate https://qiita.com/Sossiii/items/6c8916f96176991f19aa I would like you to read this article. It was also very popular on Twitter.

We also publish a skill map (roadmap) for getting into practice from inexperienced. https://qiita.com/Sossiii/items/e2c846d12f2f5db7c426

Steps for API communication

Step 0: What is an API in the first place?

https://qiita.com/NagaokaKenichi/items/df4c8455ab527aeacf02 It's described in detail in this article, but it's difficult for beginners. To give you a rough idea as you read through this article, It is for ** to receive ** certain information ** from ** external ** by ** communication **. For example, when developing an app, you can operate event information on the management screen. There are times when you want to send to the app side. For that reason, we cannot update the app one by one. When using API communication, "If there is event information, display it in the app" You can implement logic such as.

Step 1: Check the data structure you receive

Now that you have a rough understanding of the API Next, I will explain the procedure for using it. The first thing to do is to check ** what data will be sent **.

The general flow of API communication processing is ** 1 ・ Throw a request 2. Receive data 3. Map the received data 4. Actually use the mapped data ** But at the mapping stage If the data type is different or the structure of the receiving side is different The mapping will fail. Therefore, first check ** what kind of data will be sent **.

The only way to check is to search the URL. https://covid19-japan-web-api.now.sh/api//v1/prefectures For example, at this URL that publishes the infection status of coronavirus Let's access it. スクリーンショット 2020-11-06 11.19.37.png

What you need to check here is "key", "value and its type", and "data structure". The key corresponds to id, name_ja, name_en, etc. in the image. value corresponds to 1 (Int), "Hokkaido" (String), "Hokkaido" (String) The data structure is a hierarchy {} or an array or [].

I don't know why I have to check these without outputting, so Ah, please read on to see if there is such a thing.

Step 2: Prepare the mapping, write the model

Once you know the data structure that is being sent, you can map it. I will write the code. From the data sent in the mapping Extract the data you want to use and make it available in the language of the user.

https://covid19-japan-web-api.now.sh/api//v1/prefectures Consider the case of using id, name_ja, pcr from the data sent in. In this case, paying attention to the key, value, and structure of the part you want to know, it will be as follows.

[ 
  { 
    id:1
    name_ja: "Hokkaido",
    ...
    pcr: 85892,
  },
  { 
    id:2
    name_ja: "Aomori",
    ...
    pcr: 5350,
  },
...
]

Now let's write a model for actually mapping. After opening Xcode, let's create a new file. The file name is Covid.swift.

//Covid.swift file
struct CovidInfo: Codable {
  let id: Int
  let nameJa: String
  let pcr: Int
  //Converting variables of two or more words to snakecase with CodingKey
  //Snake case is applied when mapping
  enum CodingKeys: String, CodingKey {
    case nameJa = "name_ja"
  }
}

Basically, variable / constant names are lower camel case (https://wa3.i-3-i.info/word13956.html) I wrote it as above (nameJa) because I need to write it in The JSON data returned is ** name_ja **, isn't it?

When mapping, if the writing method here is different, it will fail, so You need to make it the same shape. ** Coding Key ** plays an active role there. enum CodingKey: String, CodingKey {} You are matching with.

Now that the saucer for mapping is complete, In the next step, we will actually make a request.

Step 3: Create a function to make a request

For API processing, create a new API file and make it common. Let's call it API.swift. I'd like to use a library such as Alamofire or Moya, For those who are just starting out, we will proceed without using the library here.

struct CovidAPI {
    static func getPrefectures(completion: @escaping ([CovidInfo]) -> Void) {
        let url = URL(string: "https://covid19-japan-web-api.now.sh/api//v1/prefectures")
        let request = URLRequest(url: url!)
        URLSession.shared.dataTask(with: request) { (data, response, error) in
            
            if let data = data {
                let result = try! JSONDecoder().decode([CovidInfo].self, from: data)
                completion(result)
            }
        }.resume()
    }
}

I will explain in order from the top.

static func getPrefectures(completion: @escaping ([CovidInfo]) -> Void)
//To CovidInfo[]Is attached when checking the data structure in Step 1[ ]Was attached(Was in an array)
//Because. Since multiple data will fly, I will make it an array in the call processing.
//By adding static, you do not need to instantiate the Covid API from the outside
//I am trying to call it.
//If there is static
CovidAPI.getPrefectures()
//If there is no static
CovidAPI().getPrefectures()
//I'm using closures as arguments.
//The data in the function cannot be carried over by default.
//@It is possible by adding escaping.
URLSession.shared.dataTask(with: request) { (data, response, error) in
            if let data = data {
                let result = try! JSONDecoder().decode([CovidInfo].self, from: data)
                completion(result)
            }
        }.resume()
//I was actually making a request on the URLSession line{()}Inside is the response.
//Since data will be the data we want, only if data is returned in an if let statement
//You are mapping.
//Match data to CovidInfo type(mapping)Assign to the constant result
//Passed to completion.(Returning data to the caller)

Step 4: Try to call

Now that we are ready to use API communication, let's call it from the view controller.

//ViewController.swift
CovidAPI.getPrefectures(completion: {(result: [CovidInfo]) -> Void in
    DispatchQueue.main.async {
        idLabel.text = "\(result.id)"
        nameLabel.text = "\(result.nameJa)"
        pcrLabel.text = "\(result.pcr)"
    }
})

For idLabel, nameLabel, pcrLabel, prepare UILabel () by yourself and place it on the screen. Once the data is reflected, the steps in this article are complete.

in conclusion

Did you understand the flow of processing around communication? ** 1 ・ Throw a request 2. Receive data 3. Map the received data 4. Actually use the mapped data ** I will do it in the flow of, but for the mapping of 3 ** 1 ・ Check the returned data (data name and data structure) 2. Decide the data you want to receive and prepare a saucer (type) ** Two steps are required. Communication processing fails just because the saucer type and variable name are different, so It is no exaggeration to say that the two steps here are the most important.

It is one of the implementations where the fledgling is more difficult, so I hope it will be helpful as much as possible.

Recommended Posts

[Swift, a must-see for fledgling! ] Let's understand the implementation of communication processing of WebAPI
Aiming for a basic understanding of the flow of recursive processing
Let's dig a little deeper into the Stream API, which I understand is a rewrite of for.
[Swift / Beginner] Let's write the functions around communication in a separate file
Implementation of asynchronous processing for single tenant in Tomcat
[For beginners] Quickly understand the basics of Java 8 Lambda
[Swift] This is the solution! Illustration of Delegate implementation
I put in a gem bullet (for those who don't notice the N + 1 problem themselves)
A note for those who live with JMockit
[Swift, a must-see for fledgling! ] Let's understand the implementation of communication processing of WebAPI
Create an Android app for those who don't want to play music on the speaker
For those who have deleted a document in Firestore but the subcollection does not disappear
Let's take a look at the screen of Quant Analyzer!
Let's try the implementation to find the area of the triangle that we did in the training for newcomers