Skip to main content

Swift中的基础网络通讯实现 – PART 1

BASIC NETWORKING IN SWIFT – PART 1

最近打算做一个Swift和SwiftUI的系列教学。用一些简单的例子和实践来完成App开发中常见的问题和解决。这个系列适合接触iOS开发的初学者。虽然Objective- C还没有完全“死硬”,但Swift早已成为iOS和macOS开发的主流选择,在加上SwiftUI这几年的突飞猛进,对于开发者而言,特别是刚刚入门的iOS开发者,这个组合应该不会错。本篇我们来看看Swift最基本的网络请求,例如请求某个远端API的实现。

作为测试对象,我选择Open Weather Map最为测试API提供商。注册过程很简单,选择免费的天气API,新建一个应用,并获取API Key即可。

OpenWeatherMap是一个广泛使用的天气数据提供商,它提供了一套全球范围内的天气API服务。下面是关于OpenWeatherMap的一些信息:

数据覆盖范围:OpenWeatherMap提供全球范围内的天气数据,包括当前天气情况、逐小时预报和未来几天的天气预报。他们的数据覆盖了几乎所有的地理位置,无论是城市、乡村还是偏远地区。

天气信息:OpenWeatherMap提供了丰富的天气信息,包括温度、湿度、气压、风速、降水量、天气状况描述等。此外,他们还提供了天文数据,如日出日落时间、月相等。

API功能:OpenWeatherMapAPI具有广泛的功能,包括获取实时天气数据、逐小时和逐日预报、天气地图、历史天气数据等。你可以根据自己的需求选择合适的API来获取所需的天气信息。

文档和开发者支持:OpenWeatherMap提供了详细的API文档和示例代码,帮助开发者快速接入和使用他们的服务。他们还提供了开发者支持,可以通过论坛、电子邮件或社交媒体与他们的团队联系,以解决任何问题或疑问。

总体而言,OpenWeatherMap被广泛认可为可靠的天气数据提供商,并且其API功能丰富,适合各种天气相关的应用和项目。然而,正如使用任何第三方API一样,你应该仔细阅读他们的使用条款和价格政策,并确保你的使用符合他们的规定。

在开始Xcode中的开发工作之前,我们现在测试一下OpenWeatherMap的API调用。这里我强烈推荐一款API开发和测试工具:RapidAPI

从OpenWeatherMap的文档中我们可以找到‘当前天气’的API请求规范如下:

HTML
https://api.openweathermap.org/data/2.5/weather?lat={lat}&lon={lon}&appid={APIkey}

详细的请求参数和格式可以在文档中查询,这里我们只需要考虑API密钥和位置经纬度。exclude可以排出过滤掉一些返回数据内容,这个功能是OpenWeatherMap API 3.0中新增的,让我们的数据更加简洁,效率也更高。

下面我们用RapidAPI来测试API请求:

右侧返回的JSON结果已经格式化,一目了然。从返回JSON可以读出如天气、温度、湿度、风速风向以及城市名称和日出日落时间等等信息。其实提取以下一部分字段就足以构建一个具备基本功能的天气预报App了。

JSON
{
  "coord": {
    "lon": 136.9064,
    "lat": 35.1815
  },
  "weather": [
    {
      "id": 804,
      "main": "Clouds",
      "description": "overcast clouds",
      "icon": "04n"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 293.48,
    "feels_like": 293.81,
    "temp_min": 292.32,
    "temp_max": 294.04,
    "pressure": 1007,
    "humidity": 86
  },
  "visibility": 10000,
  "wind": {
    "speed": 0.45,
    "deg": 87,
    "gust": 1.34
  },
  "clouds": {
    "all": 100
  },
  "dt": 1683387127,
  "sys": {
    "type": 2,
    "id": 2001167,
    "country": "JP",
    "sunrise": 1683402960,
    "sunset": 1683452514
  },
  "timezone": 32400,
  "id": 1856057,
  "name": "Nagoya",
  "cod": 200
}

接下来我们新建一个Xcode项目,名为SwiftNetworking,注意使用Swift作为开发语言。因本章不太涉及SwiftUI内容,所以使用什么方式构建UI都可以。此例选择了SwiftUI。

首先我在SwiftNetworkingApp.swift中建立了一个字符串变量API_KEY,用以储存API密钥。只是简单测试的话也可以直接写到URL字符串中。

Swift
//  SwiftNetworkingApp.swift
//  SwiftNetworking
import SwiftUI

var API_KEY = "***************************"

@main
struct SwiftNetworkingApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

虽然我们直接可以在ContentView.swift也就是SwiftUI文件中编写调用函数,单位了代码的整洁和可读性,我还是建议把数据逻辑层和用户界面层分开。所以这里新建一个WeatherEngine.swift来存放API请求的函数。并且在App运行时调用请求函数。

Swift
//  WeatherEngine.swift
//  SwiftNetworking

import Foundation

func fetchWeatherData() {
    print("API call runs here")
}


//  ContentView.swift
//  SwiftNetworking

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundColor(.accentColor)
            Text("Hello, world!")
        }
        .onAppear(){

            fetchWeatherData()

        }

        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

在这个函数里,我们使用 JSONSerialization 对响应数据进行解析,将其转换为字典([String: Any])。然后,可以根据需要来处理天气数据。这里我们只是简单的把返回数据log出来。这里我们在每一步都进行了异常处理,虽然只是log出error.localizedDescription字符串,但在程序开发过程中这是非常重要的,当结构和逻辑越发复杂的时候,这个习惯可以让你更容易找出异常原因。

至此,当你运行程序的时候,Debug窗口便会打印出通过网络请求API并返回的结果。

最后我们在界面中添加一个按钮,点击按钮以后再调用fetchWeatherData()函数。以下是修改后的ContentView.swift

Swift
//  ContentView.swift
//  SwiftNetworking

import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Button(action: {
                fetchWeatherData()
            }) {
                Text("Fetch Weather Data")
                    .padding()
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .cornerRadius(10)
            }
        }
//        .onAppear(){
//            fetchWeatherData()
//        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

至此我们已经完成了基本的网络API请求,并返回了数据。下一章我们会详细处理返回的数据,提取、转换及格式化需要的字段,并在UI中显示结果。

Happy coding!

API, Development, iOS, Networking, OpenWeatherMap, Swift, Tutorial