Web上にあるRSS形式の記事をダウンロードしてテーブルビューに書く

こんにちは、久しぶりの投稿になります。
将来作成したいアプリのための勉強用として今回は簡易的なニュースリーダーアプリを作成しました。
・UITableView
・RSSデータの解析
大きく分けてこの２つについて学びました。



##1.RSSデータの取得と解析##
####RSS形式のデータ
今回のニュースリーダーアプリでは搭載する記事のデータをインターネットからRSS形式でダウンロードしてます。RSSデータは要素名と要素の2つで構成されています。

```swift

<item>
<title>アップルの特許技術</title>
<link>https:wired.jp/2018/10/03/</link>
</item>
```

このような構成のデータをXMLParserクラスを使用して解析した上で各プロパティに仕分けします。



####XMLParserクラスを用いたRSSデータの解析
RSSデータの解析にはXMLParserクラスを使う。このクラスはデータ解析は実行してくれるが解析結果をどのように使うかは関知しない。
行いたい処理はデリゲートに書く。
ここではListViewControllerクラスをデリゲートに指定した。

```swift
class ListViewController : UITableViewController , XMLParserDelegate {
```


####データのダウンロード
RSSデータは以下のコードでインターネットからダウンロードしました。

```swift
func startDownload() {
        self.items = []//記事の重複を防ぐ
        if let url = URL(
            string: "WebサイトのURL"){
            if let parser = XMLParser(contentsOf: url) {
                self.parser = parser
                self.parser.delegate = self
                self.parser.parse()
            }
        }
}
```

最初に全ての記事が入る箱を空の状態にします。古いデータが入ったままで再度データをダウンロードすると重複する記事が生成されるためこの処理を最初に行っています。
　次にニュース記事があるWebサイトのURLを指定している。
今回はWIREDというWebサイトのRSSフィードのURLを指定しています。
続いてXMLParser のインスタンスを作成しています。
引数の前には前の行で作成したURLを指定します。
そして、parserのデリゲートに「self」(ListViewController)を指定し最後にparse()メソッドを呼び出すことでデータの解析を開始しています。

####内容を取り出す
続いて要素名ではなく要素を取り出します。

```swift
 func parser(_ parser:XMLParser , foundCharacters string : String) {
        self.currentString += string
    }
    //内容を取り出す処理
```
引数stringには見つかった記事の内容が格納されています。
ここでは引数の中身を変数currentString+=演算子を使って追加していきます。

####解析したデータを表示する
全てのデータの解析が終了すると自動的に次のメソッドが呼び出されます。

```swift
//解析したデータを表示する処理
func parserDidEndDocument(_ parser: XMLParser) {
        self.tableView.reloadData()
    }
```

```swift
//テーブルビューの内容を置き換える処理

 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    //表示するセルの作成
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell" , for: indexPath)
        cell.textLabel?.text = items[indexPath.row].title
        return cell
    }

```

👇ListTableViewController

```swift

import UIKit


class ListViewController: UITableViewController , XMLParserDelegate {
    var parser:XMLParser!
    var items = [Item]()
    var item:Item?
    var currentString = ""
    //表示するセルの数
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }
    
    //表示するセルの作成
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell" , for: indexPath)
        cell.textLabel?.text = items[indexPath.row].title
        return cell
    }
    
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        startDounload()
    }
    //startdownload
    
    //データのダウンロード
    func startDounload() {
        self.items = []//記事の重複を防ぐ
        if let url = URL(
            string: "https://blog.benchmarkemail.com//rss.xml"){
            if let parser = XMLParser(contentsOf: url) {
                self.parser = parser
                self.parser.delegate = self
                self.parser.parse()
            }
        }
}

    
    func parser(_ parser: XMLParser,
                didStartElement elementName: String,
                namespaceURI: String?,
                qualifiedName  qName: String?,
                attributes attributeDict: [String : String]) {
        self.currentString = ""
        if elementName == "item" {
            self.item = Item()
        }
    }
    
    
    
    func parser(_ parser:XMLParser , foundCharacters string : String) {
        self.currentString += string
    }
    //内容を取り出す処理
    
    func parser(_ parser: XMLParser,
                didEndElement elementName: String,
                namespaceURI: String?,
                qualifiedName qName: String?) {
        switch elementName {
        case "title": self.item?.title = currentString
        case "link": self.item?.link = currentString
        case "item": self.items.append(self.item!)
        default : break
        }
    }
    
    
    func parserDidEndDocument(_ parser: XMLParser) {
        self.tableView.reloadData()
    }
    
    
    override func prepare(for segue: UIStoryboardSegue, sender : Any?) {
        if let indexPath = self.tableView.indexPathForSelectedRow {
            let item = items[indexPath.row]
            let controller = segue.destination as! DetailViewController
            controller.title = item.title
            controller.link = item.link
        }
    }
}
```

##追記：WebKitViewの役割
ウェブビューを使うことでアプリの中にブラウザ機能を追加することが可能になるんだそう。
**(1)WebKitフレームワークをインポートする**
**(2)ストーリーボードにウェブビューを追加する**
**(3)ウェブビューにURLを渡す**

この他にもブラウザに必要な機能がたくさん提供されているそうなのでブラウザを使ったアプリを考えている人はドキュメントを見ておいた方が良いのかも‥