2014年12月23日

【書籍】「レベルアップ Objective-C iOS7/Xcode5対応」沼田 哲史



本書のはじめにには「Xcodeを使ってiOSまたはOS X用の簡単なアプリケーションをいくつか書いたことのあるObjective-Cプログラミング中級者以上の方々を対象としております」と書かれているが、中級者というのは本書に書かれているようなことができる人のことだと思うのです。

が、言葉の定義は別としてある程度アプリの開発ができるようになった人が、より効率良く、また品質の高いアプリケーションの開発をするためにObjective-C的なコードを書き、開発ツールを使いこなすために知っておくといい内容をまとめている本だというのは間違いない。

Xcodeの効率的な使い方は知っているようでいて使いこなせていない人も多いだろう。Xcodeの機能は本書で書かれているのはほんのさわり。もっと豊富で開発効率を高めるのに役立つ機能はまだまだもっと沢山あるのだ。それでもここに書かれている程度のことは使えるようになると開発効率は高まる。興味のある人は自分でメニューを色々触ってみてもいい。Xcodeの解説本はXcode5向けで少し違う部分もあるが複数出版されているので参照してみてください。

その他、デバッグの手法、バージョン管理、テスト駆動開発の手順、リファクタリングや、メモリ管理、マルチスレッドなど。知っておくべき基本的な事柄がならぶ。メモリ管理やマルチスレッド(ブロック記法、GCD、オペレーションキューなど)は現代的アプリケーションの開発ではなくてはならない手法だ。どれもさわりだけの記述だが、こういうことを知っていれば実際に使ってみる機会ができてより深く知りたければそのトピックについて調べることもできる。

ただ闇雲に動くプログラムを作る段階から、このような手法を使えるようになれば開発効率も高まり、より高度なアプリケーションの開発もできるようになるのではないだろうか。

ところで、本書ではデータ管理手法として、Core DataとiCloudに一章を割き多くのページ数使って解説している。それぞれサンプルアプリもステップバイステップで開発して細かく使用方法を述べている。だが、これらは特定のフレームワークの使い方であり本書の他の部分で記述されている内容とは異なる内容のようで違和感がある。

著者の意図としては、データの永続化は少し大きなアプリケーションでは当然重要なことになるし、iOS的なアプリケーション開発では、単純に保存するだけではなく多様な方法を考えるべきということなのかもしれない。特にiCloudについては様々な機器の連携が必要なiOSアプリでは重要な選択肢なのかもしれない。

なお、本書はiOS7/Xcode5対応となっており、現在のiOS8/Xcode6よりは古いバージョン向けのものになっています。ですが、述べられている内容は基本的なことがらばかりで決して古い内容ではなく現在でもなんら変わりなく使える技術です。Xcodeのメニューなどの位置は少し変わっているかもしれませんが、4から5ほどの違いはないはずです。

ちなみにここ最近紹介している本は1年前頃に出版された本だと気がついているでしょうか?そう昨年の年末年始あるいは春休み時期に時間をとって勉強しようとしていた本です。1年前はやり気だけあって時間がとれなかったものを今頃になって時間ができたので読み進めている次第です。
posted by 永遠製作所 at 15:05| 東京 ☀| Comment(0) | TrackBack(0) | iPhone/iPod touch | このブログの読者になる | 更新情報をチェックする

2014年12月14日

【書籍】『作りながら覚える iOSプログラミング iOS 7 対応版』沼田哲史




iOS7対応のプログラミング入門書。色々なサンプルアプリを開発しながら、iOS7 & Xcode5時代のプログラム方法を習得できる。

簡単な開発環境の説明と、公開するための章を除く7章で各章ごとに1本づつよくあるタイプのアプリを開発してそれぞれのタイプでどのように開発していけばいいかを説明している。各アプリは簡単とはいえそれなりに実用的でデザインやいくつかの独自追加機能を加えれば実際にリリース可能なのではないかと思える。

あまり前置きに時間をかけずにいきなりコードを書き始められる入門書。こういう型のアプリにはこういうクラスが必要で、そのクラスはそもそも何ができてどういうメソッドがあって……と長々と説明されると退屈して興味を失う人も多いだろう。

本書では、まずこういうアプリを作ります。じゃあプロジェクトを作って……といきなり作業に入れるので飽きる暇はない。実装も段階的に進めるので、沢山コードを入力して最後にようやく動かしてみたらエラーで動かない、なんて心配はない。ちょっと機能を追加して実行、また追加して実行、ちょっと変更して実行と進めるので作っている楽しさを味わえるし変化が目に見えるからコードの意味がわかりやすい。実際の開発にも役立つ習慣づけにいい。

GUI操作の多いIBも必要な部分のスクリーンショットがちゃんとあって再現しやすい。iOS8 & Xcode6だとレイアウト方法などが変わるのでちょっと初心者にはわかりにくかもしれないので改訂版が待たれる。

今回入力するコード、その後で説明する部分だけ取り出したコード断片、章末に完全なコードとそれぞれ背景色を変えて記述していあるのもわかりやすい点。

クラスやメソッドの説明は実際にアプリで使うものにしぼっているのでコンパクト。使っているフレームワークの詳細や他にどんなことができるかなどは後で調べればいいこと。まずはやりたい事、必要なことだけにしぼって実際に動くアプリを作るアプローチは、手っ取り早くアプリを作る体験をして動かす面白さから学ぶのに大事。

章タイトルだけだと従来からあるiOSアプリサンプルと変わらないように見えるが、実際にはiOS7らしい機能を使っていて、自然とiOS7らしいアプリが開発できている。

特にiOS7らしいとことろはSptiteKit,DynamicType,Speech,AutoLayoutなど。

サンプルコードは以下の出版元サイトからダウンロードできる。画像、サウンドリソースなどを使うとか、エラー発生時の比較用にして、コードは自分で入力しながら、覚えるのがよいと思う。
http://isbn.sbcr.jp/72045/

■目次:
第1章 開発環境を整える
第2章 カラーエディタを作る
第3章 時計アプリを作る
第4章 メモ帳アプリを作る
第5章 曲名の読み上げアプリを作る
第6章 動画ビューアを作る
第7章 メディアアートを作る
第8章 地図アプリを作る
第9章 App Storeでアプリを公開しよう

Kindle版もあります。

posted by 永遠製作所 at 17:34| 東京 ☀| Comment(0) | TrackBack(0) | iPhone/iPod touch | このブログの読者になる | 更新情報をチェックする

2014年11月30日

SpriteKitで使うマスクファイルの作り方

SpriteKitのSKCropNodeではマスクノードで指定した画像マスクで画面に表示する部分を制限することができる。そしてそのマスクはmaskNodeに登録したSKNodeであればよいように見えるが、iOS8.1ではPathで作成したマスクは有効に機能していないようで、SKSpriteNodeでしかも画像ファイルから生成したものでなければならないようだ。

ではそのSKSpriteNodeに設定する画像をどう作ればいいのか。

マスク画像はalpha値のみが関係している。SKCropNodeで設定されたマスク画像で覆われた部分のうち、マスク画像のalpha値が0でない部分が切り取られて表示される。感覚的にはalpha値が0の部分が透けて見えるように思えるがそういうことではない。むしろ逆になっている。

マスク画像のalpha値がマスクされる画像に複製されているように想像するといいでしょう。

付属ファイルは星の部分が透けて見えるようになっている。星の外側がalpha=0でこの部分に置かれた画像は見えない。


SKSpriteNode *mask;
// うまくいかない
// mask = [SKSpriteNode spriteNodeWithColor:[SKColor blackColor]
// size: CGSizeMake(100, 100)];
mask = [[SKSpriteNode alloc] initWithImageNamed:@"mask"];
mask.position = myLabel.position;
[self addChild:mask];
self.cropNode = [SKCropNode node];
self.cropNode.maskNode = mask;
self.cropNode.position = CGPointZero;

[self addChild:self.cropNode];


SKCropNodeを付けたSceneにアタッチしたSKNodeが切り取られる。

mask.png
posted by 永遠製作所 at 18:08| 東京 ☁| Comment(0) | TrackBack(0) | iPhone/iPod touch | このブログの読者になる | 更新情報をチェックする

2014年11月29日

SpriteKitの衝突判定処理でのノードの順序(改訂版)

SpriteKitでは、物理体はcontactTestBitMaskを設定しておけば衝突時に-didBeginContact:が呼ばれる。だが、bodyAとbodyBにはどちらの物理体が設定されているかは不定なので、毎回冗長な判定処理をかかないといけない。

というのを昨日書いたが、よく考えればSKPhysicsContactのメセッドにしたほうが使い回しが効くので書き換えた。英語が苦手なので名前が適切かどうかはよくわからない。


@interface SKPhysicsContact (Compare)
-(BOOL)contactsWithName:(NSString *)firstName
and:(NSString *)secondName;
- (void)orderdBodyA:(SKPhysicsBody**)bodyA
bodyB:(SKPhysicsBody**)bodyB;
@end

@implementation SKPhysicsContact (Compare)

-(BOOL)contactsWithName:(NSString *)firstName
and:(NSString *)secondName
{
if ([self.bodyA.node.name isEqualToString:firstName]) {
if ([self.bodyB.node.name isEqualToString:secondName]) {
return YES;
}
} else if ([self.bodyB.node.name isEqualToString:firstName]) {
if ([self.bodyA.node.name isEqualToString:secondName]) {
return YES;
}
}
return NO;
}

- (void)orderdBodyA:(SKPhysicsBody**)bodyA
bodyB:(SKPhysicsBody**)bodyB
{
if ( !bodyA || !bodyB ) return;
if ( self.bodyA.categoryBitMask > self.bodyB.categoryBitMask ) {
*bodyA = self.bodyA;
*bodyB = self.bodyB;
} else {
*bodyA = self.bodyB;
*bodyB = self.bodyA;
}
}

@end
posted by 永遠製作所 at 00:57| 東京 ☁| Comment(0) | TrackBack(0) | iPhone/iPod touch | このブログの読者になる | 更新情報をチェックする

2014年11月28日

SpriteKitの衝突判定処理でのノードの順序

SpriteKitでは、物理体はcontactTestBitMaskを設定しておけば衝突時に-didBeginContact:が呼ばれる。だが、bodyAとbodyBにはどちらの物理体が設定されているのだろうか?これがわからなければ毎回冗長な判定処理をかかないといけない。


if ( ([nameA isEqualToString:kEnemyName] &&
[nameB isEqualToString:kWeponName]) ||
([nameA isEqualToString:kEnemyName] &&
[nameB isEqualToString:kWeponName]) ) {
}


と思って調べたのだが、少なくともアップルの文書中で見る限り衝突時のA, Bの順序は決まっていないようだ。サンプルコードを見ても何が入るかは任意でありどちらになにが来てもいいように対応すべきという姿勢のようだ。

だが、実装者によってはA,Bの比較は固定であるノードは必ずどちらかにしかこないという前提で書かれたコードを見ることがある。どうも一定の規則に従っているようだ。ブログなどを検索したところ、先に生成されたノードが必ずA、後に生成されたノードがBとなるという記述を見つけた。本当にそうなのだろうか?そうだとしてもAPIリファレンスで明記されないかぎり「現時点での実装ではそうなる」という以上の意味はないだろう。

だが毎回両方の比較をするのは大変。考えられるのは二つ、比較用の関数を用意すること。またはある規則に従って並べ替えること。


static inline BOOL CompareEqual(SKPhysicsContact *contact,
NSString *first,NSString *second)
{
if ([contact.bodyA.node.name isEqualToString:first]) {
if ([contact.bodyB.node.name isEqualToString:second]) {
return YES;
}
} else if ([contact.bodyB.node.name isEqualToString:first]) {
if ([contact.bodyA.node.name isEqualToString:second]) {
return YES;
}
}
return NO;
}


これは前出比較を関数にしただけ。


+ (void)orderdBodies:(SKPhysicsContact *)contact
bodyA:(SKPhysicsBody**)bodyA
bodyB:(SKPhysicsBody**)bodyB
{
if ( !bodyA || !bodyB ) return;
if ( contact.bodyA.categoryBitMask > contact.bodyB.categoryBitMask ) {
*bodyA = contact.bodyA;
*bodyB = contact.bodyB;
} else {
*bodyA = contact.bodyB;
*bodyB = contact.bodyA;
}
}


これはカテゴリービットマスクでより上位のビットが1であるほうがA、そうでないほうがBになるようにして返すメソッド。これで比較は決まった順序でできる。
posted by 永遠製作所 at 01:26| 東京 ☀| Comment(0) | TrackBack(0) | iPhone/iPod touch | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。