SwiftだけでRSSリーダーを作ってみた

はじめまして。

iOSエンジニアの木村です。

eurekaでは、カップル専用SNS、Couples(カップルズ)のiOS開発を担当しています。

 

今回は、話題の言語「Swift」について書きたいと思います。

Swiftとは

swift-hero

 

WWDC2014で新しいプログラミング言語、Swiftが発表されました。

現在のiOSの主要な開発言語であるObjective-Cと比較すると、より短く、安全に書くことが可能になります。

また、実行速度もObjective-Cより速いです。

さらに、Objective-Cと共存が可能というところもポイントで、 既存のプロジェクトを徐々に移行していく、ということが可能ではないかと思います。

SwiftだけでRSSリーダーを作ってみた

Swiftで書かれたサンプルはいくつかありますが、
部分的に既存のObjective-Cのライブラリを使用しており、
Swiftだけで書かれたものが見当たりませんでした。

ということで、今回は本当にSwiftだけで書いてみようと思います。

 

今回、表示したいRSSはXMLなのでパースするためにNSXMLParserを使いました。

ネットワーク通信はNSURLSessionを使用しています。

まずはデータを取得してみます

var entries : NSMutableArray!
override func viewDidLoad() {
    super.viewDidLoad()
    entries = NSMutableArray()
    let url : NSURL = NSURL(string: "http://qiita.com/tags/Swift/feed.atom")
    self.rssUrl = url
}

tableViewの表示で使用する、entriesを初期化しておき、
取得したいRSSのNSURLを作成しrssUrlに代入します。

 

var rssUrl : NSURL!
{
    didSet{
        // rssUrlに値が入ると以下の処理が呼び出される
        // 便利な記述方法なので、若干無理やりですが使ってみました!
        let request : NSURLRequest = NSURLRequest(URL:self.rssUrl)
        func completionBlock(data: NSData!, response: NSURLResponse!, error: NSError!) -> Void {
            var parser : NSXMLParser = NSXMLParser(data: data)
            parser.delegate = self;
            parser.parse()
        }
        var task : NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler:completionBlock)
        task.resume()
    }
}

rssUrlは、代入されるとNSURLSessionを使用しRSSのダウンロードを始めるようにしてみました。

 

ダウンロードが完了次第completionBlockが呼ばれ、

NSXMLParserを使用しXMLのパースを開始します。

次はデータ格納部分です

// NSXMLParserDelegate
var parseKey : String!
var tmpEntry : Entry!

let entryKey = "entry"
let titleKey = "title"
let urlKey   = "url"

 XMLをパースするために必要な変数と、取得したいキーの宣言をしておきます。

 

func parser(parser: NSXMLParser!, didStartElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!, attributes attributeDict: NSDictionary!)
{
   parseKey = nil
   if elementName == entryKey {
       tmpEntry = Entry()
       entries.addObject(tmpEntry)
   } else {
       parseKey = elementName
   }
}

func parser(parser: NSXMLParser!, didEndElement elementName: String!, namespaceURI: String!, qualifiedName qName: String!)
{
    parseKey = nil;
}

entryキーが見つかったタイミングでEntryオブジェクトを生成し、entriesに追加。

 

func parser(parser: NSXMLParser!, foundCharacters string: String!)
{
    if parseKey? == titleKey {
        if tmpEntry {
            var tmpString : String? = tmpEntry?.title;
            tmpEntry.title = tmpString? ? tmpString! + string : string
        }
    } else if parseKey? == urlKey {
            tmpEntry.url = string
    }
}

データをEntryオブジェクトに格納。

Entryオブジェクトは

– title

– url

を宣言しています。

 

func parserDidEndDocument(parser: NSXMLParser!)
{
    self.tableView.reloadData()
}

パース終了時、tableViewを更新。

 

tableViewの表示部分

func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int
{
    return self.entries.count;
}

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell!
{
    var cell : TableViewCell = tableView.dequeueReusableCellWithIdentifier("TableViewCell", forIndexPath: indexPath) as TableViewCell
    let entry : Entry! = entries.objectAtIndex(indexPath.row) as Entry
    cell.textLabel.text = entry.title
    cell.textLabel.font = UIFont.systemFontOfSize(12)
    cell.textLabel.numberOfLines = 0
    return cell
}

 

 

swift_1

 

 

次に、タップした時の画面遷移部分です。

func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!)
{
    var controller : DetailViewController = self.storyboard.instantiateViewControllerWithIdentifier("DetailViewController") as DetailViewController
    var entry : Entry! = entries.objectAtIndex(indexPath.row) as Entry
    controller.entry = entry
    self.navigationController.pushViewController(controller, animated: true)
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
}

 

swift_2

 

これで、記事一覧を表示してタップで閲覧、という簡単なRSSリーダーの完成です!

 

今回の処理のフローは、以下です。

 

・NSURLSessionでXMLをダウンロード

・NSXMLParserでXMLをパース

・Entryタグに合わせてEntryオブジェクトを作成し配列に挿入

・パース終了時にTableViewを更新

感想

Swiftで書いてみた感想ですが、

 

基本的にはObjective-Cと同じ感覚で書くことが出来ました。

また、変数に値が入るタイミングをハンドリングできる機能もとても便利に感じます。

ほかにもいくつかハンドリングできるものがあり、

このような機能を使うことで今までより、きれいなコードを書くことが出来るのでは?と思いました。

 

Swift、今後が楽しみです。

プロジェクトファイルはこちら