DTCoreText で NSAttributedString を高速に描画

先日、HTML 文字列を NSAttributedString に変換する方法を書いた。

NSAttributedString を UILabel の attributedText にセットするだけで、 お手軽に HTML を表示できるけど、UILabel は描画が非常に遅い。 UIWebView と同じか、少しマシかも、ってくらいには待たされる。 記事のサマリー程度でこの遅さ、ちょっと使えない。

実用的な速度で NSAttributedString を描画するライブラリを探してみたところ、 DTCoreText というのが良さそうだった。

低レイヤー API の CoreText を使って、ビューに直接テキストを描画するライブラリ。

例えば、DTCoreText が提供する DTAttributedTextView を使うことで、

self.attributedTextView = DTAttributedTextView(frame: self.view.bounds)
self.view.addSubview(self.attributedTextView)

let html = "<h1><a href=\"http://tnakamura.hatenablog.com\">Title</a></h1>"
    + "<ul>"
    + "<li><strong>Item1</strong></li>"
    + "<li><i>Item2</i></li>"
    + "</ul>"
let data = html.dataUsingEncoding(
    NSUTF8StringEncoding, allowLossyConversion: true)
let attrStr = NSAttributedString(HTMLData: data, documentAttributes: nil)

self.attributedTextView.attributedString = attrStr

HTML を画面いっぱいに表示することができる。速度も気にならない。

f:id:griefworker:20141127065245p:plain

今回はコードで直接サブビューに追加したけど、DTAttributedTextView は UIScrollView を継承しているので、 Storyboard に UIScrollView を貼り付けてカスタムクラスを指定する方法でも使える。 AutoLayout を設定するなら、そちらの方法がいいかも。

HTML を NSAttributedString に変換する

HTML の文字列は

let html = "<h1><a href=\"http://tnakamura.hatenablog.com\">Title</a></h1>"
    + "<ul>"
    + "<li><strong>Item1</strong></li>"
    + "<li><i>Item2</i></li>"
    + "</ul>"
let data = html.dataUsingEncoding(
    NSUTF8StringEncoding, allowLossyConversion: true)
let attrStr = NSAttributedString(HTMLData: data, documentAttributes: nil)

という風に NSData を経由して NSAttributedString に変換できる。

こいつを NSAttributedString を表示できるコントロール、例えば UILabel に

self.label.attributedText = attrText

でセットすれば、UIWebView を使わずに HTML を表示することができる。

ちんやのすき焼き丼

福岡市博多区中洲にある、すき焼きの名店『ちんや』の 『すき焼き丼』が絶品という情報を得たので行ってみた。

ちんやは以前、1F のレストランに焼肉定食を食べに行ったけど、 すき焼き丼を出しているのは、外の階段を上がった 2F のようだ。 2F でもランチをやっているとは知らなかったな。

f:id:griefworker:20141122122116j:plain

運よくお座敷が空いていたので、店についてすぐ案内された。 案内されて速攻注文を聞かれてビビッたけど、既に決めていたので間髪入れずに注文。 もちろん『すき焼き丼』を。

まずはサラダ。

f:id:griefworker:20141122115001j:plain

青じその風味が爽やかだった。

そして待望のすき焼き丼。

f:id:griefworker:20141122120518j:plain

見た目結構なボリューム。 豆腐、ネギ、白菜はどれも味が染みていた。 肉は脂が甘くて、口に入れるとすっとほどける柔らかさ。 素材がいいんで、シンプルな味付けで十分美味だった。

期待通りの味で満足。 1400円とランチにしてはお高いけど、 10000 円くらいする夜のすき焼きと比べたら敷居が低いと思う。

関連ランキング:すき焼き | 中洲川端駅呉服町駅天神南駅

SourceKitService が頻繁にクラッシュする

OS X Yosemite + Xcode 6 の環境にアップグレードしてからというもの、Xcode でコード書いていると SourceKitService Crashed や SourceKitService Terminated が頻繁に発生するようになった。

ネットで調べると同じ問題に遭遇した人は多いみたいで、stackoverflow に投稿を見つけた。

いくつか回答があるが、どうやら DerivedData を削除することで改善したらしい。

試しに

$ rm -rf ~/Library/Developer/Xcode/DerivedData

で削除してみたところ、確かに SourceKitService Crashed は発生しなくなった。 今のところは、だけど。

博多一幸舎 大名本家

かなり久しぶりに、博多一幸舎大名本家に行ってみた。 そういえば、大名店が移転して大名本家になって初めてな気がする。

f:id:griefworker:20141115111031j:plain

大名本家では鶏つけ麺がメニューに加わったので、 今回はそれを注文。

f:id:griefworker:20141115112105j:plain

麺は中太。 今までの店は中盛でも腹がパンパンになっていたんだけど、 ここの中盛は丁度良い量だった。

f:id:griefworker:20141115111931j:plain

つけ汁は見た目あっさりしてそうだったけど、 鶏の旨みがしっかり出ていて美味だった。 初めて味わうタイプのつけ汁。

f:id:griefworker:20141115112256j:plain

もちろん、ミニチャーハンも注文。 ラーメン屋のチャーハンはやっぱり旨い。

今回、初めて一幸舎のつけ麺を食べたけど、 IH ヒーターが全ての席に設置してあるのが凄く良い。 おかげでつけ汁が、舌を火傷するくらいに最後まで熱々。 つけ麺は麺が冷たいので、 IH ヒーターもしくは、つけ汁を温めなおすサービスは必須だと思う。

関連ランキング:ラーメン | 赤坂駅西鉄福岡駅(天神)薬院大通駅

AFNetworking と ReactiveCocoa を組み合わせる

ReactiveCocoa を導入したからには使い倒す方針でやっていて、 AFNetworking を使った Web API 呼び出しは、次のようにして RACSignal 化している。

let signal = RACSignal.createSignal({ (subscriber) -> RACDisposable! in
    let manager = AFHTTPRequestOperationManager(baseURL:  baseURL)

    let operation = manager.GET(
        path,
        parameters: parameters,
        success: { (operation, response) -> Void in
            subscriber.sendNext(response)
            subscriber.sendCompleted()
        },
        failure: { (operation, error) -> Void in
            subscriber.sendError(error)
        }
    )

    return RACDisposable(block: {
        operation.cancel()
    })
)
return signal

POST や PUT、DELETE も同じ。 たいして難しいコードじゃないけど、RACSignal 化するコードを何度も書くのはDRY じゃないよね。

実は、AFNetworking の拡張があったりする。

こいつを使えば、先ほどのコードを次のように書き変えることができる。

let manager = AFHTTPRequestOperationManager(baseURL:  baseURL)
let signal = manager.rac_GET(path, parameters: parameters)
return signal

成功・失敗のコールバックを引数で渡す必要がなくなって、見た目が非常にシンプル。

五穀 けやき通り店

前から行こうと思っていた『五穀 けやき通り店』にようやく行けた。 久しぶりの外食。

f:id:griefworker:20141108114018j:plain

店に着いたときは既に1組並んでいたけど、席数が少ないため、1組で済んでラッキーだったのかもしれない。 20分くらい待ってようやく席に案内された。

並んでいる間に注文するのは決めていて、席に座って即『メンオムランチ』を注文。 明太子オムライスとコーンサラダとドリンク、あとデザートまで付いていてお得感高い。 周りのテーブルもほとんどメンオムランチだった気がする。

f:id:griefworker:20141108120646j:plain

ドリンクはコーラにした。 他にもコーヒー・紅茶・野菜ジュースが選べる。

f:id:griefworker:20141108120642j:plain

コーンサラダ。言うほどコーンのってない、普通のサラダ。 そういえば、ワカメ入っているサラダは福岡にあまり食べた記憶ないな。

f:id:griefworker:20141108121505j:plain

お待ちかねの明太子オムライス。 スプーンで玉子を割ってみると

f:id:griefworker:20141108121525j:plain

実に旨そう。実際旨かった。

予想以上に明太子がしっかり存在を主張していて、 めんたいライスのピリッとした刺激と、玉子のまろやかさが、 打ち消しあわずにお互い引き立てあっていた。

半分ほど食べてケチャップをかけると、 ケチャップの甘さと酸味で、違った味に変わる。 これまた旨い。

f:id:griefworker:20141108122159j:plain

最後はデザートにチーズケーキ。 ベリーソースの酸味が口の中をさっぱりさせてくれた。

かなりコストパフォーマンスが高いランチだと思う。 明太子という変り種オムライスだったけど、 期待以上の味に満足。

関連ランキング:オムライス | 赤坂駅薬院大通駅桜坂駅