GraphQL vs REST在Swift中:2025年iOS开发者该如何选择

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

引言:REST vs GraphQL——Swift新时代中的经典对决



曾几何时,在Objective-C和基于选择器调度的时代,REST与GraphQL之间的选择并不那么尖锐。REST是王者,JSON是其忠实的随从。但时代变了。Swift已成为一种拥有强类型系统的语言,async/await、Codable以及Apollo iOS等强大框架相继出现。如今,“REST还是GraphQL?”这个问题有了新的含义:“哪个能为我的Swift项目带来更多收益?”



在本文中,我们不会复述维基百科。我们将以一个教育平台的真实iOS应用为例(没错,就是那个PythonLib),看看每种方法在Swift代码中的实际表现。您将了解到何时REST仍然占据主导,以及何时GraphQL才是真正的救星。



核心要点:REST与GraphQL的主要区别



对于刚接触这个话题的人来说,先了解一些基本概念。



  • REST — 一种架构风格,其中每个资源(用户、课程、课时)都有其自己的URL。您会获得服务器决定返回的固定数据结构——通常包含大量冗余数据。
  • GraphQL — 一种查询语言。您自己决定需要哪些字段。一个入口点(/graphql)和一个查询可以替代多个REST请求。


理论上,GraphQL看起来像一颗银弹。但在Swift项目中存在一些细微差别,我们将在实践中逐一分析。



示例1:获取用户资料及其课程



Swift中的REST方法(URLSession + Codable)



假设我们有一个经典的REST API。要显示用户资料和课程列表,需要两个请求:



// 模型struct UserProfile: Codable {    let id: Int    let name: String    let email: String    let avatarURL: String}

struct Course: Codable { let id: Int let title: String let progress: Double}

// 网络层func fetchUserProfile(userId: Int) async throws -> UserProfile { let url = URL(string: "https://api.pythonlib.ru/users/\\(userId)")! let (data, _) = try await URLSession.shared.data(from: url) return try JSONDecoder().decode(UserProfile.self, from: data)}

func fetchCourses(userId: Int) async throws -> [Course] { let url = URL(string: "https://api.pythonlib.ru/users/\\(userId)/courses")! let (data, _) = try await URLSession.shared.data(from: url) return try JSONDecoder().decode([Course].self, from: data)}

// 使用let profile = try await fetchUserProfile(userId: 42)let courses = try await fetchCourses(userId: 42)


一切简单且可预测。但有一个问题:即使我们只需要姓名和邮箱,也会获取到资料的所有字段。此外,还需要两次网络请求。在慢速连接下,这会造成性能问题。



Swift中的GraphQL方法(Apollo iOS)



现在,通过GraphQL实现同样的功能。首先,在.graphql文件中定义查询:



query GetUserWithCourses($userId: ID!) {    user(id: $userId) {        id        name        email        courses {            id            title            progress        }    }}


Apollo会自动生成类型化的Swift代码。在Xcode中,它看起来像这样:



import Apollo

let apolloClient = ApolloClient(url: URL(string: "https://api.pythonlib.ru/graphql")!)

func fetchUserWithCourses(userId: Int) async throws -> GetUserWithCoursesQuery.Data { return try await withCheckedThrowingContinuation { continuation in apolloClient.fetch(query: GetUserWithCoursesQuery(userId: userId)) { result in switch result { case .success(let graphQLResult): if let data = graphQLResult.data { continuation.resume(returning: data) } else if let errors = graphQLResult.errors {

博客

书籍推荐