[iOS] plistから情報を取得してUITableViewに表示 in Swift3

アプリの設定情報を保存するxxx.plistですが、本来はxmlなのでデータを抜き出してアプリのUIに表示できます。

## どんなときに必要か
自分が必要になったケースとしては、

1. ソースと一緒にリモートリポジトリに公開したくないAPIキーをローカルのplistに保存して読み込む
2. Carthageでインストールしたライブラリのライセンス情報をアプリに表示する

ときに必要でした。
今回 2. のケースで説明します。

## 1. info.plistからデータを抜き出す
Swift3版を。
Swift2から結構書き方が違っています。

環境：
Swift3.1
Xcode8.3

### 例) plistに保存しているライブラリのライセンス情報を取得する
ちなみにCarthageのライセンス情報は[このSwiftScript](https://github.com/pietbrauer/CarthageLicenseScript)で抜き出すと便利です。

こんなplistがあります。

<img width="762" alt="plist.png" src="https://qiita-image-store.s3.amazonaws.com/0/30423/347b73c8-1d1a-1d83-2485-6b934e1c77dd.png">


抜き出します。

``` Swift
import Foundation

// plist名はtypoを防ぐためEnumで管理
enum FileName: String {
    case key = "Key"
    case licenses = "Licenses"
}

// ライセンス構造体
struct License {
    
    // ライセンス名を格納する配列
    var titles: [String] = []
    
    init?() {
        guard let licenses: [[String : Any]] = parsePlist(FileName.licenses) else {
            return nil
        }
        // ライセンス情報の配列からtitleだけ抜き出す。
        // flatMapを使えばnilを省いた配列を返してくれるので便利
        titles = licenses.flatMap { $0["title"] as? String }
    }
    
    
    // plistに保存しているライセンス情報をparseするメソッド
    private func parsePlist(_ fileName: FileName) -> [[String: Any]]? {
        // 何かしらparseに失敗したらnilを返す
        guard let filePath: URL = Bundle.main.url(forResource: fileName.rawValue, withExtension: "plist") else {
            return nil
        }
        do {
            let data = try Data(contentsOf: filePath)
            return try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? [[String: Any]]
        }
        catch {
            return nil
        }
    }
}
```

## 2. TableViewにライセンス情報を表示
License構造体のtitleプロパティを表示するだけ

``` Swift

import UIKit

class LicensesViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var tableView: UITableView!
    let license = License()
    var titles: [String] {
        return license?.titles ?? []
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.separatorInset = UIEdgeInsets.zero
        tableView.delegate = self
        tableView.dataSource = self
        
        self.navigationItem.title = "Acknowledgements"
        self.tableView.backgroundColor = UIColor.bg
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        tableView.tableFooterView = UIView(frame: CGRect.zero)
    }
    
    
    // MARK: - TableView Delegate
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return titles.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell")!
        cell.textLabel?.text = titles[indexPath.row]
        cell.accessoryType = .disclosureIndicator
        return cell
    }
}
```

## できた!
<img width="375" alt="dekita.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/30423/1f56f586-4c6f-cf40-9629-68389b46834d.png">


## 参考サイト
[【Swift】APIキーをschemeごとに分けつつ、パブリックなリポジトリにキーを公開したくない時](http://qiita.com/taji-taji/items/85ffa52a575147c03017)
http://stackoverflow.com/questions/39910461/how-to-read-from-a-plist-with-swift-3-ios-app