はじめに
SwiftでNews APIを使ってニュースアプリを作ってみたいと思います。
初心者にもわかりやすく、AutoLayoutの設定、デザインパターン、コードの可読性もしっかり守っているので、APIの入門記事としてはぴったりかなと。
では始めていきます。ぜひ最後までご覧ください。
UIの設計
このように配置していきます。
NewsListTableViewControllerからDetailViewControllerまでのsegueのidentifierに"toWeb"とつけてください。
ArticleTableViewCellを作り、IBOutlet接続します。
import Foundation
import UIKit
class ArticleTableViewCell: UITableViewCell {
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
@IBOutlet weak var urlImageView: UIImageView!
}
全体設計
APIの取得
まず、APIの取得からやっていきたいと思います。
NewsAPIを使います。
操作は以下。
ログインをする、またアカウントがない場合は新規アカウント登録を行う。
それができたら、ここでAPIKeyを取得する。
そしてこのようにAPIを叩くと、JSONデータを変換してくれます。
Webservice
今回のAPIにおいてのロジックを管理するWebserviceを書いていきます。
import Foundation
class Webservice {
func getArticles(with urlString:String,completion:@escaping ([Article]?) -> ()){
if let url = URL(string: urlString) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { data, response, error in
if error != nil {
print(error!)
completion(nil)
}
if let safeData = data {
// print(response)
let decoder = JSONDecoder()
do {
let decodedData = try decoder.decode(ArticleList.self, from: safeData)
completion(decodedData.articles)
//プリントをしながら中身を確認する
//print(decodedData.articles[0].description)
} catch {
print(String(describing: error))
}
}
}
task.resume()
}
}
}
Article
レスポンスしたデータをデコードするためのArticleを作成していきます。
import Foundation
struct ArticleList: Codable {
let articles: [Article]
}
struct Article: Codable{
let title:String
let description:String
let urlToImage:String
let url:String
}
NewsListTableViewController
最後に取得したデータをViewに反映させる、またUITableViewの操作のためにViewControllerを作っていきます。
その前に画像のキャッシュのために便利なSDWebImageというライブラリを使いたいと思います。
SDWebImageの詳しい説明、導入の仕方などはこれらの記事を見るとわかると思います。
import Foundation
import UIKit
import SDWebImage
class NewsListTableViewViewController: UITableViewController{
fileprivate var articles: [Article] = []
var urlArticle = ""
override func viewDidLoad() {
super.viewDidLoad()
setup()
}
private func setup(){
//ここにAPIKeyを挿入する
let urlString = "https://newsapi.org/v2/top-headlines?country=us&apiKey=[APIKey]"
Webservice().getArticles(with: urlString,completion: { (articles) in
guard let data = articles else{
return
}
self.articles = data
print(articles![0].title)
print(articles![0].description)
DispatchQueue.main.async {
self.tableView.reloadData()
}
})
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? ArticleTableViewCell else {
fatalError("ArticleTableViewCell not found")
}
cell.titleLabel.text = articles[indexPath.row].title
cell.descriptionLabel.text = articles[indexPath.row].description
cell.urlImageView.sd_setImage(with: URL(string: articles[indexPath.row].urlToImage), completed: nil)
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return articles.count
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.urlArticle = articles[indexPath.row].url
self.performSegue(withIdentifier: "toWeb", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toWeb" {
let detailVC = segue.destination as! DetailViewController
detailVC.urlString = self.urlArticle
}
}
}
そして最後はクリックした記事を閲覧させるためにWKWebViewを使っていきたいと思います。
import UIKit
import WebKit
class DetailViewController: UIViewController , WKUIDelegate{
var webView: WKWebView!
var urlString = ""
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
let myURL = URL(string:urlString)
let myRequest = URLRequest(url: myURL!)
webView.load(myRequest)
}
}
WKWebViewの処理はWKWebViewのドキュメントを確認しながら学んでください。
完成形はこちらを参照してください。
指摘点がありましたら、コメントでもよろしくお願いします。