ワシはワシが育てる

週刊少年ジャンプと任天堂のゲームが三度のメシより好きです。

AppCodeでlinker command failedが出た場合の対処法

iOS開発でのコーディングにはXcodeではなくAppCodeを使用しておりますが、しばしば「linker command failed」のエラーに悩まされています。

cocoapodsの依存ライブラリが存在しないよというエラーなのですが、ほとんどの場合キャッシュやプロジェクトファイルの問題だったりします。

理解が浅くてどこがどのように影響しているのか把握していないのですが、とりあえず以下の対応で大抵の場合は大丈夫かと思います。

  • ~/Library/Caches/appCode31以下のフォルダのcachesDerivedDataの中身を削除する
  • .ideaフォルダを削除して開き直す
  • 上に加えてプロジェクトを開くときにフォルダではなくxcworkspaceを指定して開く

また、そもそもAppCode自体のエラーなのかどうかを判別するために、まずはXcodeでビルドできるかどうかを試してみるといいと思います。

Rails4.2にあげるとローカルIPでアクセスできない問題

Rails4.2にバージョンアップ後、いつも通り起動しローカルIPを通じてスマホからアクセスしようとしたところつながらない状況に。

Railsのバージョンアップが原因だとほぼ特定していたのでRelease Noteを見ると、Rackの変更によって、デフォルトではlocalhost127.0.0.1でしかアクセス出来ないようになっているようです。

Release Noteはこちらを参照

対処法はrails serverコマンドの際のオプションとして-bに0.0.0.0を指定することです。(以前のRackのデフォルトコマンドと同じ)

rails s(erver) -b 0.0.0.0

ちなみに-bというのはbinding ipを意味しているらしいです。

Unicorn+NginxでリバースプロキシしたときにFacebookのOAuthでつまづいた

RailsアプリをUnicornで動かし、Nginxをリバースプロキシとして前面に置く構成。

その際にFacebookのOAuthを利用すると「指定されたURLは、アプリケーションの設定で許可されていません。」というエラーメッセージが表示されてしまいました。

原因はリバースプロキシを使用した際にホスト名が引き継がれておらず、Facebook側に正しいURLが認識されていなかったためでした。
そこで対象のRailsアプリに該当するnginx設定ファイルに以下の行を挿入します。

proxy_set_header Host $http_host;

ローカルで動かしている時には生じない問題なので厄介ですね。

UIActionSheetのキャンセルボタンが効かなくなる問題の対処法

iOS8 SDKを使用しているとiOS7でキャンセルボタンが効かなくなることがあるようで、開発中のアプリで実際に何度か遭遇しました。ちなみに毎回発生するわけではありません。

対処法はUIActionSheetのshowInViewの対象をviewからview.windowに変更するだけです。

UIView *rootView;

UIActionSheet *actionSheet = [[UIActionSheet alloc]initWith ~ ];
[actionSheet.showInView rootView.window];

iOSをほぼ1ヶ月毎日やりつづけた感想(AndroidやJSとの比較とか)

先月からiOSを始めてほぼ1ヶ月毎日続けた感想です。
まだ不慣れなところも多く未熟な意見なので参考程度に捉えてください。

Objective-Cは割りとすぐ慣れた

初めは妙な型名とかメソッドの書き方とか、iOSの長ったらしい構文に強い先入観がありましたが、案外やってれば慣れます。
先入観で嫌がってやらないのは非常に勿体無いです。(過去の自分への問いかけ)

Xcodeが使いづらい

Android開発の延長線でiOS開発を始めたのですが、Android Studioと比べてXcodeは使いづらく、実際に生産性にかなり影響しました。
単体で記事にするかもですが、Jetbrainsが出しているAppCodeが非常にオススメです。Xcodeに慣れていないというのもありますが、誇張ではなく本当に生産性が1.5~2倍変わりました。

Swift採用を諦めた

元から採用するのは難しいと思っていましたが、Swiftを一度試してみて早い段階で限界を感じて諦めました。
理由としてはAppCodeのSwift対応が不十分なこと、Xcodeでもリファクタリングにまだ対応していないこと、Ob-Cとの互換性があると言ってもライブラリによってはバグが出ることなどが原因です。

Androidとの比較

個人的にプログラミングとしてはAndroidの方がやりやすいです。
まだ不慣れなせいか気持ち悪く感じるのは、Storyboardを使用するとロジックとViewが混在してしまうこと、さらにViewやControllerを静的に管理できないことなどです。

Androidや画像やレイアウト、Viewも静的に紐付けられる一方、iOSは画像が存在しなければ何も表示されず、レイアウトや対応するViewがなければ落ちるなど作ってて結構ヒヤヒヤします。

またInterface Builderを用いたAutolayoutも個人的には好きではなく、例えば共通のスタイルを定義できなかったり、色や値の定数が使えなかったり、動的に要素を非表示にするのが面倒だったりということが要因です。

ただ弁解しておくと、これらのように不便に感じる点はあるのですが、総じて見ると決して開発しづらいわけではないです。(単にAndroidとの比較的な意味です)

ネイティブとWebとの比較

一応去年の前半まではWeb制作がメインたったので、Webとネイティブ(iOS + Android)の比較を。

やはり小規模で短期間で作るとなると小回りが効くWebの方が生産性は高いです。ただ一定規模以上かつ、パフォーマンスを求めるとむしろネイティブの効率が上まってきます。

特にHTML+JSだと無限スクロールでほぼ間違いなくパフォーマンス問題にぶち当たるので、用途ごとに最適化されたコンポーネントを使用できるのはネイティブの強みです。

個人的な感想としては、静的言語とIDEの恩恵にどっぷり浸ってしまうと、もはやJSに戻りたくなくなってます。

あと、特にAndroidGoogleのドキュメントが素晴らしくよく出来ているので、むしろWebより学習コスト低いと思います。(全般的にネイティブはレールが敷かれていて、やることがハッキリしているので思ったより学習コスト低いです)

RubyMineが最強すぎて感動する

最近Qiita界隈でRubyMine特集がされていたこともあって、RubyMine使ってみたら最強すぎて感動しました。

理由は色々ありますが書くのが面倒なので箇条書きにします。

  • 補完が想像以上に強力
    • gemでも、環境依存ファイルの定数でも補完してくれます
    • エディタが空気を読んで型を取ってくれるので、データベースカラムに相当するモデルインスタンスメソッドすら補完してくれます(これ超重要!)
  • 動的言語なのに元ソースに飛べる
    • 上に書いたように変数の型をエディタが察してくれるので、対応するメソッドなどにジャンプしたり、逆に使用されている箇所も一覧で表示できます(ただし静的言語ほど正確ではない)
    • 型情報から引数がおかしい場合は、素晴らしいことにちゃんとエラーを出してくれます
  • リファクタリングが便利
    • JetBrains系ではお馴染みですがリファクタリングが便利です。スコープ内の変数名の変更が定番ですが、クラス名などグローバルな名前は型情報からプロジェクト全体のリファクタリングをしてくれます。(上述したとおり静的言語ほど正確ではないので、大規模な変更は実用的ではない)
  • 関連ファイルにすぐ飛べる
    • コントローラーに対応するview、モデルに対応するrspecなど関連するファイルは一覧で表示され、すぐにジャンプすることができます。
    • viewではインスタンス変数を汲み取ってくれるので、おかしな変数を使っていたら警告を出してくれます。
    • viewを書いてて分割したくなったらすぐにpartial化することができます
  • バージョン管理が楽ちん
    • プロジェクトに対応するgitを自動で読み込んでくれます。
    • コミットログから差分を「-」「+」ではなく、実際の前後バージョンを確認できます。
    • 当然リモートのリポジトリも対応しています。

まだまだ書き足りないですが、とにかく「かゆいところに手が届く」という言葉につきます。
もっと早く使っていればよかった。。。

Railsのafter_commitでcreateやupdateなどを判別する

上の記事でも触れていたことですが、after_commit時のレコードからcreate,update,destroyなどのアクションを判別する正規の方法を見つけたので書きます。

以前の記事を書いた時にstackoverflowなどを調べて良さ気だったのが「transaction_include_action(:action)」というメソッドだったのですが、こちらのAPI dockを見ての通りRails4.0以降では廃止になっています。

ならRails4.0以降ではどうなるんだろうと思って、API dockの右下を見ると代替メソッドっぽい「transaction_include_any_action(:actions)」というのが見つかります。

メソッド名からも連想できるように後者は複数のアクションを判別できるようになっており、パワーアップ(?)しているようです。

ということでcreated_atとupdated_atを比較するというような原始的な方法は捨てて、「transaction_include_any_action?」を使って判別すればいいだけということですね。

例えばobserverを使って判別する場合は以下のようになります。

class HogeObserver < ActiveRecord::Observer
  def after_commit(record)
    if record.send(:transaction_include_any_action?, [:create])
      # create時のアクション
    elsif record.send(:transaction_include_any_action?, [:update])
      # update時のアクション
    end
  end
end

後から気付いたのですが「activerecord-committed_observer」というライブラリでも同じ実装方法だったので、今度こそこれが正解だと思います。