Swift初心者がシンプルなRSSリーダーを作る。
プログラミングの基礎はVisualBasic6.0で学び、perlも少々いじってましたが、今回Swiftを使えるようになりたいと思い、本を購入して勉強しました。
流石にたった2日でマスターは出来ませんでしたが、SwiftUI対応 たった2日でマスターできるiPhoneアプリ開発集中講座 Xcode 12/iOS 14対応は、良い教本ですね。
そこで、Swift勉強の為に本に載っていたサンプルのコードも使いつつシンプルなRSSををリーダーを作ってみました。
目 次
1. 参考とした記事と本
- 【SwiftUI】外部サイトからデータを取得する|カピ通信
- SwiftでシンプルなRSSリーダーを作る(Yahooニュース編)
- SwiftUI対応 たった2日でマスターできるiPhoneアプリ開発集中講座 Xcode 12/iOS 14対応
2. 機能はシンプルで2点のみ
- RSSを取得して「タイトル」「日付」の2つをListに表示する。
- 記事をタッチして該当のニュースをSafariViewで表示する
完成イメージ
3. 開発環境
- iMac(Late2012)
- macOS Catalina(10.15.7)
- Xcode 12.4
- Swift 5.3.2
- 使用外部ライブラリ なし
4. ソースコードDownload
5. 全体ソース
はじめに全体ソースをお見せしますが、元となるコードは、【SwiftUI】外部サイトからデータを取得する|カピ通信のコードを使用してます。
//
// ContentView.swift
// Simple RSS Reader
//
// Created by Assy on 2021/09/05.
//
import SwiftUI
//RSS情報をまとめる構造体
struct Response: Codable {
let items: [Result]
}
//記事詳細
struct Result: Codable {
let title: String
let link: URL
let guid: String
let pubDate: String
}
struct ContentView: View {
//空のJSON配列を生成
@State private var results = [Result]()
//SafariViewの表示有無を管理する変数
@State var showSafari = false
var body: some View {
NavigationView {
List(results, id: \.guid) { item in
Button(action: {
//SafariViewを表示する
showSafari.toggle()
}) {
VStack(alignment: .leading) {
Text(item.title ) //記事タイトル
.font(.headline)
Text(item.pubDate) //記事の日付
}
}
.sheet(isPresented: self.$showSafari, content: {
//記事リンクをSafariViewで表示する
SafariView(url: item.link)
//画面下部をいっぱいになるようにセーフエリア外までいっぱいになるように指定
.edgesIgnoringSafeArea(.bottom)
})
}.navigationTitle("Simple RSS Reader")
}.onAppear(perform: loadData) //RSSデータ読み込み処理
}
//RSSデータ読み込み処理
func loadData() {
//取得したいRSSを指定
let rss_url = "https://news.yahoo.co.jp/rss/categories/it.xml"
//指定したRSSをJSONに変換するAPIと連結して取得する
let url: URL = URL(string:"https://api.rss2json.com/v1/api.json?rss_url=\(rss_url)")!
let task: URLSessionTask = URLSession.shared.dataTask(with: url, completionHandler: {(data, response, error) in
//データ取得チェック
if let data = data {
//JSON→Responseオブジェクト変換
let decoder = JSONDecoder()
guard let decodedResponse = try? decoder.decode(Response.self, from: data) else {
return
}
//RSS情報をUIに適用
DispatchQueue.main.async {
results = decodedResponse.items
}
} else {
//データが取得できなかった場合の処理
print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
}
})
task.resume()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
SafariViewの部分のコードは教本(SwiftUI対応 たった2日でマスターできるiPhoneアプリ開発集中講座 Xcode 12/iOS 14対応)のコードをそのまま使用しました。
//
// SafariView.swift
// Simple RSS Reader
//
// Created by Assy on 2021/09/05.
//
import SwiftUI
import SafariServices
//SFSafariViewConrollerを起動する構造体
struct SafariView: UIViewControllerRepresentable {
//表示するウェブサイトのURLを受ける変数
var url: URL
//表示するViewを生成するときに実行
func makeUIViewController(context: Context) -> SFSafariViewController {
//Safariを起動
return SFSafariViewController(url: url)
}
//Viewが更新されたときに実行
func updateUIViewController(_ uiViewController: SFSafariViewController, context: Context) {
//処理なし
}
}
6. コードの追加及び修正箇所
元となるコードに追加したり修正した箇所は下記の通りですが、きちんと取得出来るまでに相当に時間が掛かってしまいました。
JsonDecoderまでは良かったんだけど、その後のCodable構造体に読み込む時にエラーが出ていて表示出来なかったのが一番難しかった所でしょうか。
まあ、JSONの構造からモデルを作成する箇所が間違っていたのですがね。
- 使用しているのはYahoo!ニュースのRSSです。(https://news.yahoo.co.jp/rss/categories/it.xml)
- RSS(XML)をJSONに変換するAPIを通してJSONを取得するコードを追加
- 取得したJSONに基づいてCodableを修正
- JsonDecoderでCodable構造体に読み込み取得した記事をListに表示
- 表示した項目一つ一つをButton化して記事をタップしたらSafariViewを開くようにコードを追加
7. 今後、追加予定の機能
勉強も兼ねて、このコードを発展させて、もう少し使えるようにしてみたいので今後追加予定の機能です。
機能追加したら、新しく記事を書きたいと思います。
- 下に引っ張って更新
- 下スクロールすると過去の記事が表示されるようにする
- サムネイル画像を取得し表示する
- タブメニューで記事の種類を選択できるようにする