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

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

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

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

Swift で ReactiveCocoa を使う

はじめに

SwiftiOS アプリを実装し直すにあたって、 ただ Swift に翻訳するだけではつまらないので、 MVVM アーキテクチャで実装することに決めた。

View/ViewController と ViewModel のバインド、 イベントや非同期 API 呼び出しのインタフェースを統一するために、 ReactiveCocoa を導入する。

CocoaPods で RactiveCocoa をインストール

Podfile に

pod "ReactiveCocoa"

を追加して pod install

Bridging-Header で ReactiveCocoa のヘッダーファイルをインポート

<プロジェクト名>-Bridging-Header.h に次の行を追加。

#import <ReactiveCocoa/ReactiveCocoa.h>

これで Swift から ReactiveCocoa が使えるようになった。

RACSignal を作成してみる

API 非同期呼び出しのインタフェースを RACSignal で統一したいので、RACSignal でラップする。

class CommentViewModel: NSObject {
    var ownerName: String!
    var repoName: String!
    var issueId: Int!
    var comment: String?

    func postComment() -> RACSignal {
        return RACSignal.createSignal({ (subscriber) -> RACDisposable! in
            let manager = AFHTTPRequestOperationManager.manager()
            let operation = manager.POST(
                "/repositories/¥(self.ownerName)/¥(self.repoName)/issues/¥(self.issueId)/comments",
                parameters: ["comment": self.comment],
                success: { (operation, response) -> Void in
                    subscriber.sendNext(response)
                    subscriber.sendCompleted()
                },
                failure: { (operation, error) -> Void in
                    subscriber.sendError(error)
                }
            )
            return RACDisposable(block: { () -> Void in
                operation.cancel()
            })
        })
    }
}

UITextView に ViewModel をバインドしてみる

UITextView の text に変更があったら即座に ViewModel に反映させてみる。 Objective-C では RAC マクロを使ってバインドできるけど、Swift では RAC マクロが使えないので、 低レイヤーのメソッドを使うしかなかった。

self.commentTextView.rac_textSignal().setKeyPath("comment", onObject: self.viewModel)

ちなみに、同じことが UITextField でも可能。

ViewModel のプロパティを UIBarButtonItem にバインドしてみる

例えば、「ViewModel の comment プロパティが空ではないとき UIBarButtonItem を有効にする」 というのを ReactiveCocoa で実装するとこんな感じ。

self.viewModel.rac_valuesForKeyPath(
    "comment",
    observer: self.viewModel
).map({ (next) -> AnyObject! in
    let newComment = next as String
    return !newComment.isEmpty
}).setKeyPath("enabled", onObject: self.postButtonItem)

RACCommand を使って ViewModel のメソッドも UIBarButtonItem にバインドしてみる

「ViewModel の comment プロパティが空ではないとき UIBarButtonItem を有効にする」だけでなく、 UIBarButtonItem をタップしたときのアクションも併せて ReactiveCocoa で実装。

let commentSignal = self.viewModel.rac_valuesForKeyPath(
    "comment",
    observer: self.viewModel
).map({ (next) -> AnyObject! in
    let newComment = next as String
    return !newComment.isEmpty
})

let postCommand = RACCommand(
    enabled: commentSignal,
    signalBlock: { (input) -> RACSignal! in
        return self.viewModel.postComment()
    }
)

self.postButtonItem.rac_command = postCommand

ReactiveCocoa を使ってみて

インタフェースを RACSignal に統一できるので、コードを書きやすい。 特に RACSignal 化した非同期呼び出しは、引数でコールバックを渡す必要がないのでスッキリする。

ただ、コントロールにバインドする RACSignal や RACCommand は、 ViewModel のプロパティとして実装したほうが良かった。

ReactiveCocoa 難しい。 RACSignal にようやく慣れてきたけど、 RACCommand やその他の機能はまだ理解が追いついていない。

Bootstrap の Tooltip で改行する方法

title 属性に <br> タグを含んだ文字列、data-html 属性に true を設定すればいい。

<span rel="tooltip"
  data-toggle="tooltip"
  data-placement="right"
  data-html="true"
  title="1行目<br/>2行目">
  コンテンツ
</span>

Rails なら simple_format を使うと便利。

<span rel="tooltip"
  data-toggle="tooltip"
  data-placement="right"
  data-html="true"
  title="<%= simple_format(item.tooltip) %>">
  <%= item.content %>
</span>

Swift で AFNetworking を使う

CocoaPods で AFNetworking をインストール

Podfile に

pod "AFNetworking"

を追加して pod install 実行。

Bridging-Header で AFNetworking のヘッダーをインポート

<プロジェクト名>-Bridging-Header.h に

#import <AFNetworking/AFNetworking.h>
#import <AFNetworking/UIImageView+AFNetworking.h>

を追加。

画像の非同期ダウンロード機能も使いたいので、 AFNetworking.h だけでなく UIImageView+AFNetworking.h もインポートしている。

AFHTTPRequestOperationManger を使ってみる

func loadRepositories() {
    let manager = self.createManager()
    manager.GET(
        "user/repositories/",
        parameters: nil,
        success: { (operation, json) -> Void in
            let array = json as NSArray

            // 配列を使ってなにかやる
        },
        failure: { (operation, error) -> Void in
            // エラー処理
        }
    )
    return nil
}

private func createManager() -> AFHTTPRequestOperationManager {
    let manager = AFHTTPRequestOperationManager(baseURL: self.baseUrl)

    manager.requestSerializer = AFHTTPRequestSerializer()

    // ユーザー名とパスワードを設定
    manager.requestSerializer.setAuthorizationHeaderFieldWithUsername(
        self.username!, password: self.password!)

    return manager
}

画像を非同期にダウンロードして表示してみる

UIImageView+AFNetworking.h をインポートすると、 AFNetworking が提供する画像の非同期ダウンロードが使える。

cell.imageView.setImageWithURL(
    NSURL(string: imageUrl),
    placeholderImage: userMenuImage
)