taoru's memo

Objective-c,cocos2d,など開発についてのメモ(andoroidも少しだけ)

sedコマンドで \+ が使えなくて困ったら -E オプションを使う

タイトル通り

困ったので、冷静になって man でマニュアルを見たところ、 -E オプションで (modern) regular expressions になることがわかった

  • $ man sed
-E      Interpret regular expressions as extended (modern) regular expressions rather than basic regular expressions (BRE's).  The re_format(7) manual page fully describes both formats.

これ使うとメタ文字のエスケープとかも必要なくなって、直感的に使えるようになった

$ echo 1234abcd1234 | sed -E 's/([0-9]+)/_\1_/g'
_1234_abcd_1234_

\d とかは残念ながら使えるようにはならない

Cocos2d-x v3.1プロジェクトのspine-runtimeを更新する

Cocos2d-x v3.1プロジェクトのspine-runtimeを更新する

Spineが出力するフォーマットが変わり、Cocos2d-xに付属されているspine関係のクラスを更新する必要がでてきた。

Forumでも報告されてた

http://esotericsoftware.com/forum/viewtopic.php?f=9&t=2609&p=12750

(※バグじゃなくてatlasのフォーマット変わったからruntimeをupdateしろって言ってる)

Cocos2d-xのリポジトリへpull request出してた人もいたんだけど、 v3.0へのアップデートに集中したいとかでcloseされていた。

https://github.com/cocos2d/cocos2d-x/pull/6323

更新手順 (cocos2dx内部のspineを上書きする)

spine-runtimeを準備

$ git clone https://github.com/EsotericSoftware/spine-runtimes.git

Cocos2d-xに元から入っているspineを退避させる

Xcode上でspineディレクトリ下のReferenceを削除 68d7e492c886d82127562d0de3893834.png

ディレクトリを念のため退避

git管理してれば戻せるし要らない工程

$ cd PROJECT_ROOT/cocos2d/cocos/editor-support
$ mv spine spine.orig
$ mkdir spine

spine-runtimesから必要なファイルをもってくる

以下のディレクトリ下のファイルを

PROJECT_ROOT/cocos2d/cocos/editor-support/spine

にコピーする

  • spine-runtimes/spine-c/include/spine
  • spine-runtimes/spine-c/include/src/spine
  • spine-runtimes/cocos2dx/3.1/src/spine

Xcodeにimport

  • targetの追加忘れに注意

ここまででiOSではビルドできるようになる

Android.mkを更新する

spine/Android.mkを更新したディレクトリの状況に合わせて変更する とくにこだわりが無ければ、spineディレクトリ下のファイル名をコピペすればOK

Androidもビルドできるようになる

所感

Cocos2d-x内部にできるだけ手を加えたくないので、 外部のディレクトリに配置したかったんだけど、内部のと被るのが面倒くさそうだったので上書きした。

terminalでUUIDを自由に生成するコマンド

uuidgenというコマンドで、uuid文字列を自由に生成できる。
CoreBluetoothの開発などで、CBUUIDを新しく定義したいときなどに使う。

$ uuidgen
9B93632B-74D9-46B9-BC6A-503423BD08FC
$ uuidgen
B9EA6DEE-ADDF-477B-9CC9-58F6B2169CAF
$ uuidgen
28CEB791-3322-4F7E-A895-F651CDA9A0D0

呼び出すたびに新たに生成してくれるみたい。

複数アプリ間で同一IDを取得する

記事のタイトルつけるセンスが無い(切実)

アプリAとアプリBをタオル株式会社(仮)がリリースしたとして、
アプリAとアプリBを同時にやってくれているユーザーにインセンティブあげたい!という場合に
ユーザーを特定するための同一IDの取得が必要になる。

UUIDではアプリごとにユニークなIDになってしまうけど、開発元と端末からユニークIDを生成してくれるものがあった。
つまり、アプリAとアプリBで同じIDが取得できる!(ただし同開発元に限る)

UIDevice.h

@property(nonatomic,readonly,retain) NSUUID *identifierForVendor NS_AVAILABLE_IOS(6_0);      // a UUID that may be used to uniquely identify the device, same across apps from a single vendor.

iOS6.0以降でしか利用できないが、identifierForVenderというのが定義されている。
UIDeviceで定義されているので、以下のようにしてUUIDと同じように取得できる。

NSUUID *ideForVender = [UIDevice currentDevice].identifierForVender;
NSString *idForVenderString = [identifierForVender UUIDString];

NSUUIDをalloc initするよりちょっとだけ簡単だし、同じ会社で出してて別のIDがどうしても必要!っていうことも少なそうだから、identifierForVender使っておけばいいなじゃないかな!

iOS6.0未満はもう1割くらいしかいないらしいので、いいんじゃないかな。

追記 20130717(水)

アプリAとアプリBの認証にidentifierForVenderを使っている場合、
アプリAを1からやり直したい!と思ってアプリAを削除→再インストールしたとしても、
端末内にアプリAと同じ開発元のアプリBが残っていると、同じIDになってしまう。

データが消せない!などの弊害になりかねない感じ。

認証はUUIDを利用し、連携アプリをプレイしているかどうかのチェックのために
identifierForVenderも併用する感じがいいのかな?

参考 : デジタル・アイデンティティ技術最新動向(5):UDIDにおけるセキュリティ&プライバシー問題 (2/2)

subviewをタッチした場合にUIGestureRecognizerのイベントを無視する

UITapGestureRecoginizerや、UISwipeGestureRecognizerでviewにgestureイベントを取得するようにセットしていた場合、
タッチイベントがsubviewにいかなくなってしまう。

しかし、tableviewをタップされた場合はtableviewだけにイベントがいってほしい!
ということがあったので、回避したときのメモ。

delegate宣言

@interface MyViewController :UIViewController <UIGestureRecognizerDelegate>

UITapGestureRecognizerにdelegateをセット

UITapGestureRecognizer *tapGesture = [[[UITapGestureRecognizer alloc] initWithTarget:self
                                                                              action:@selector(handleTapGesture:)] autorelease];
tapGesture.delegate = self;
[self.view addGestureRecognizer:tapGesture];

delegateメソッドでgestureを無視したい条件のときにfalseを返す

#pragma mark - UIGestureRecognizerDelegate

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
    // gestureをセットしたview以外がタッチされた場合はgestureを無視
    if (touch.view != gestureRecognizer.view)
    {
        return false;
    }
    return true;
}

これでUIScrollViewだったり、UITableViewにイベントがいくはず。
[touch locationInView:touch.view]とかで座標をとって制御とかも使えそう。

Foundation.frameworkを検索対象に含める方法

Objective-cでのfor-inの仕様を調べていて、NSFastEnumerationに準拠しているクラスならfor-inが使えることがわかった。

そこで、どのクラスがNSFastEnumerationに準拠しているのか調べてみた。
この記事はprotocolに準拠しているクラスを探す方法についてのメモ。
結論から言うと、search navigatorで検索するのが一番早そう。

XcodeのOrganizerで調べる

Documentationで検索

XcodeのOrganizerを立ち上げ、DocumentationからNSDctionaryを検索
Conforms toの項目が準拠しているprotocolなので、ここにNSFastEnumerationが記載されていればforinが使える。
f:id:taorun:20130630001850p:plain

でもプロトコルに準拠しているクラスを探すのには向いてなさそう

しかし、OrganizerのDocumentationの検索窓にNSFastEnumerationと入れても、
NSFastEnumerationに準拠しているクラスは列挙されない。(見落としているだけかも?)

Xcodeのsearch navigatorで調べる

frameworkのヘッダファイルを検索対象に含めることができる。
つまりプロトコル宣言しているクラスを探すことができる。

search navigator -> 虫眼鏡アイコンクリック -> Show Find Options
f:id:taorun:20130630003609p:plain

"Find in" の And linked framworksにチェックを付ける
f:id:taorun:20130630004956p:plain

これでFoundation.framworkも検索対象に含まれるので、protocol準拠クラスを探すことができるようになった。


NSFastEnumerationに準拠しているクラスは、
NSArray, NSDictionary, NSHashTable, NSMapTable, NSOrderedSet, NSPointerArray, NSSet

QLOOKアクセス解析