XCode 7を入れたらnode-gypが動かなくなった件

npmを実行すると以下のエラーを得る:

ld: library not found for -lgcc_s.10.5
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Release/.node] Error 1

gccなのでXCodeが関連している模様。
関連情報:

I got the same error here, a possible error after upgrading xcode version.
I fix it with a temp solution:
cd /usr/local/lib sudo ln -s ../../lib/libSystem.B.dylib libgcc_s.10.5.dylib

とりあえず以下で対処できるらしい:

cd /usr/local/lib;
sudo ln -s ../../lib/libSystem.B.dylib libgcc_s.10.5.dylib 

んーむ・・

iOSのクラッシュログファイルをシンボリケートする

どこでクラッシュしたのか見通しを良くする

Appleから受け取ったクラッシュログは、クラッシュした状態のスタックトレースをバイナリ上のアドレスで示されています。
このままだと、内容を見てもソースコード上のどこが悪いのかさっぱり分かりません。
シンボリケートとは、主にバイナリ上のアドレスからソースコードの場所を突き止める事をいいます。

使用するコマンド

クラッシュログのシンボリケートにはsymbolicatecrashコマンドを使用すると便利です。
XCode 6では以下のパスに存在しています。

/Applications/Xcode.app/Contents/SharedFrameworks/DTDeviceKitBase.framework/Versions/A/Resources/symbolicatecrash

/usr/bin あたりにシンボリックリンクを貼っておくと吉。

必要なファイル

クラッシュログを吐いたバイナリと同じビルドのもので、以下が必要です:

  • appファイル
  • dSYMファイル

XCodeのOrganizerを開き、アーカイブ一覧から該当のビルドを探します。
次に、該当ビルドの項目を右クリックしてShow in Finderします。
開かれたディレクトリに、上記二つのファイルが存在します。

シンボリケートの実行

以下のように実行します。

export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"

symbolicatecrash -v crashファイル dSYMファイル appファイル

トラブルシューティング

DEVELOPER_DIRを予め設定しておかないと、以下のようなエラーが出ます。

Error: "DEVELOPER_DIR" is not defined at /Applications/Xcode.app/[snip]Resources/symbolicatecrash line 53.

XCConfigを複数ファイル構成にする方法

xcode-configsettings_Icon

XCConfigは、XCodeのConfiguration Settings Fileの事で、DebugやReleaseで異なるプロジェクト設定を適用する事が出来る優れモノです。
下記のように、ファイルの新規作成画面の項目として出てくるやつですね。

Screen Shot 2014-01-07 at 3.25.50 AM

CocoaPodsとか使っていると、自動生成されたXCConfigに手を加えたい時があります。
でも、pod installする度に書き換えるのは面倒ですよね。
実は、XCConfigには#includeディレクティブが用意されているので、この悩みを簡単に解決できます。
includeディレクティブはC言語と全く同じ構文です。

#!c
#include "別のxcconfigへのファイルパス"

これを使って、以下のような構成にすれば、万事うまく行きます!

XCConfig composition example

[XCode] 見づらいコードをショートカットキー一発で綺麗に整形する方法

xcode

コードの整形は手間がかかる

代入文って10行とか20行とかになると、一気に見づらくなりますよね。
特に、Interface Builder使わないでコードでUIを組み立てたりしてると、プロパティの設定処理で平気で100行になります。
例えばこんなコード・・

#!objectivec
cell.backgroundView.layer.shadowColor = [UIColor blackColor].CGColor;
cell.backgroundView.layer.shadowOffset = CGSizeMake(0, 4);
cell.backgroundView.layer.shadowOpacity = 0.8;
cell.backgroundView.layer.shadowRadius = 10;
cell.backgroundView.layer.masksToBounds = NO;
cell.backgroundView.layer.shouldRasterize = YES;
cell.backgroundView.layer.rasterizationScale = [UIScreen mainScreen].scale;
cell.backgroundView.layer.contentsScale = [[UIScreen mainScreen] scale];
cell.selectedBackgroundView.layer.shadowColor = [UIColor blackColor].CGColor;
cell.selectedBackgroundView.layer.shadowOffset = CGSizeMake(0, 4);
cell.selectedBackgroundView.layer.shadowOpacity = 0.8;
cell.selectedBackgroundView.layer.shadowRadius = 10;
cell.selectedBackgroundView.layer.masksToBounds = NO;
cell.selectedBackgroundView.layer.shouldRasterize = YES;
cell.selectedBackgroundView.layer.rasterizationScale = [UIScreen mainScreen].scale;
cell.selectedBackgroundView.layer.contentsScale = [[UIScreen mainScreen] scale];

はい、とっても汚いですね。理想は・・

#!objectivec
cell.backgroundView.layer.shadowColor                = [UIColor blackColor].CGColor;
cell.backgroundView.layer.shadowOffset               = CGSizeMake(0, 4);
cell.backgroundView.layer.shadowOpacity              = 0.8;
cell.backgroundView.layer.shadowRadius               = 10;
cell.backgroundView.layer.masksToBounds              = NO;
cell.backgroundView.layer.shouldRasterize            = YES;
cell.backgroundView.layer.rasterizationScale         = [UIScreen mainScreen].scale;
cell.backgroundView.layer.contentsScale              = [[UIScreen mainScreen] scale];
cell.selectedBackgroundView.layer.shadowColor        = [UIColor blackColor].CGColor;
cell.selectedBackgroundView.layer.shadowOffset       = CGSizeMake(0, 4);
cell.selectedBackgroundView.layer.shadowOpacity      = 0.8;
cell.selectedBackgroundView.layer.shadowRadius       = 10;
cell.selectedBackgroundView.layer.masksToBounds      = NO;
cell.selectedBackgroundView.layer.shouldRasterize    = YES;
cell.selectedBackgroundView.layer.rasterizationScale = [UIScreen mainScreen].scale;
cell.selectedBackgroundView.layer.contentsScale      = [[UIScreen mainScreen] scale];

非常に綺麗です。
でも、スペース打つの面倒くさい。。

そこで、上記のようなコードの整形をショートカットキー一発で出来るXCodeプラグインをご紹介します!

XCodeプラグイン「XAlign」が便利

XAlignは、文字通りAligningを手伝ってくれるプラグインです。

インストール方法

コマンド一発で即完了。

#!bash
$ curl github.so/XAlign/build/install.sh | sh
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   896  100   896    0     0   1805      0 --:--:-- --:--:-- --:--:--  1851
Password:
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 34311  100 34311    0     0  52104      0 --:--:-- --:--:-- --:--:-- 52543

XAlign is installed. Please Restart Your Xcode.

More info: https://github.com/qfish/XAlign/

To uninstall XAlign, `curl github.so/XAlign/build/uninstall.sh | sh`
.

XCodeを再起動しましょう。

整形の実行

以下のデモンストレーションのように、「シフト+?+X」で自動整形を実行します。

XAlign

すごいですねww 今までの苦労は一体ww
#defineプリプロセッサ文や、@property構文などにも有効なようです。

みなさんもぜひ試してみてください!

[CocoaPods] コマンド一発でライブラリのサンプルを開く方法

じゃりのツイートで知ったのでメモ。

CocoaPods に、一発でpodのサンプルプロジェクトをダウンロードして開いてくれるサブコマンドが追加されたそうな。
どういう事か説明しますね!!

CocoaPodsって何?

CocoaPods はXCodeプロジェクト向けのモジュール管理ツールです。
RubyでいうgemのObjective-C版みたいなもんですね!
世の中で公開されている多くのモジュールを、手軽にXCodeプロジェクトに追加したり削除したりできます。

コマンド一発でライブラリのサンプルを試せる

気になるライブラリを見つけてちょっと試したいなと思ったら、リポジトリをいちいち$ git cloneしてサンプルプロジェクトを開く必要がありました。
それって結構面倒ですよね。

ここでCocoaPodsの登場です。

もしライブラリがCocoaPodsに登録されていたら、任意のディレクトリで以下のコマンドを実行してみてください。

$ pod try < ライブラリ名>

自動的にリポジトリをcloneして、ヒューリスティックにサンプルプロジェクトを見つけ出して、XCodeで開いてくれます!!

pod-try

リリースされたばかりでちょっと 不具合 もあったけど、安定化も時間の問題ですね!

[XCode] LLDBでViewの階層構造を出力する

これは知っておいて損は無いTips。

po [UIView recursiveDescription] で、包含するViewを階層構造も含めて出力させる事ができます。

(lldb) po [self.view.superview recursiveDescription]
<uiviewcontrollerwrapperview: 0xbe5a870; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0xbe5a940>>
   | <uiview: 0xbe0cb10; frame = (0 0; 320 568); autoresize = W+H; layer = <CALayer: 0xbe51d70>>
   |    | <uibutton: 0xb819e90; frame = (20 60; 100 44); opaque = NO; layer = <CALayer: 0xb819690>>
   |    |    | <uibuttonlabel: 0xbe5e200; frame = (27 13; 46 18); text = 'Button'; clipsToBounds = YES; alpha = 0.2; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xbe5dfb0>>
   |    | <uibutton: 0xb81ed00; frame = (20 120; 100 44); opaque = NO; layer = <CALayer: 0xb81edf0>>
   |    |    | <uibuttonlabel: 0xbe5c760; frame = (24 13; 52 18); text = 'Sample'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xbe5c870>>