【Swift】AlamofireでAPI通信をする
はじめに
今回はQiitaAPIを叩いてAlamofireで通信していみたいと思います。
作るもの
GitHub
実装
モデル
struct Article: Codable {
let title: String
let user: User
}
struct User: Codable {
let id: String
}
コントローラー
final class ArticleListViewController: UIViewController {
@IBOutlet private weak var tableView: UITableView!
private var articles = [Article]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
getArticles()
}
}
private extension ArticleListViewController {
func getArticles() {
APIClient().request { result in
switch result {
case .success(let articles):
self.articles = articles
DispatchQueue.main.async {
self.tableView.reloadData()
}
case .failure(let error):
self.showAPIAlert(error: error)
}
}
}
func showAPIAlert(error: APIError) {
let alert = UIAlertController(title: error.title, message: nil, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "閉じる", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
}
// MARK: - UITableViewDataSource
extension ArticleListViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return articles.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = articles[indexPath.row].title
return cell
}
}
API
import Alamofire
typealias ResultHandler<T> = (Result<T, APIError>) -> Void
struct APIClient {
func request(handler: @escaping ResultHandler<[Article]>) {
let urlString = "https://qiita.com/api/v2/items"
let url = URL(string: urlString)
guard let url = URL(string: urlString) else {
handler(.failure(.invalidURL))
return
}
AF.request(urlString)
.responseJSON { response in
guard let data = response.data else {
handler(.failure(.invalidResponse))
return
}
do {
let articles = try JSONDecoder().decode([Article].self, from: data)
handler(.success(articles))
} catch {
handler(.failure(.unknown(error)))
}
}
}
}
その他
enum APIError: Error {
case invalidURL
case invalidResponse
case unknown(Error)
}
extension APIError {
var title: String {
switch self {
case .invalidResponse: return "無効なレスポンスです。"
case .invalidURL: return "無効なURLです。"
case .unknown(let error): return "予期せぬエラーが発生しました。\(error)"
}
}
}
解説
大切なところのみ解説します。
本来はurlをそのまま書いておいたりするのは良くないのですが、今回はAamofireの解説ということで、省略します。
ここでリクエストを送信しています。
AF.request(urlString)
以下のようにして、通信を行います。
APIClient().request { result in
switch result {
case .success(let articles):
self.articles = articles
DispatchQueue.main.async {
self.tableView.reloadData()
}
case .failure(let error):
self.showAPIAlert(error: error)
}
}
URLSessionとの比較
let request = URLRequest(url: url)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
handler(.failure(.unknown(error)))
return
}
if let data = data {
do {
let articles = try JSONDecoder().decode([Article].self, from: data)
handler(.success(articles))
} catch {
handler(.failure(.unknown(error)))
}
}
}
task.resume()
let request = URLRequest(url: url)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
handler(.failure(.unknown(error)))
return
}
if let data = data {
do {
let articles = try JSONDecoder().decode([Article].self, from: data)
handler(.success(articles))
} catch {
handler(.failure(.unknown(error)))
}
}
}
task.resume()
Alamofireの方が明らかに簡潔にかけていますね。
おわりに
終わりです。
Author And Source
この問題について(【Swift】AlamofireでAPI通信をする), 我々は、より多くの情報をここで見つけました https://qiita.com/REON/items/094d1b8bc7e59ea44a34著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .