プログラマブログ

by wacul

menu

2014.12.17RubyMotion で 64bit アプリに対応する

こんにちは。すっかりRubyMotionでのiOSアプリ開発にどっぷりのkyohです。 最近の趣味はダイエットですが、なかなか成果が出ません。:(

急に 64bit が来たので

世の中、だいぶ64bit環境が普及してきたこともあり、 Appleは2015年2月から、新しいアプリの申請(更新含む)において64bit対応したアプリのみを受け付けるようになります。

64-bit and iOS 8 Requirements for New Apps

これに合わせ、弊社サービスの「Clulu」も64bit対応を行いました。

およその32bit – 64bit間の差異はRubyMotionが吸収してくれる(便利!)のですが、 どうしたって一部はソース上での対応が必要です。 その最中、思わぬところで躓き、親切にもRubyMotionのContributorの方に丁寧に教えていただけたので、 簡単な解説でも書いてみようと思います。

64bit対応① まずはターゲットを追加する!

何はともあれ、ビルドターゲットに64bit環境を追加します。 RubyMotionの場合、Rakefileで次のように指定するだけです。

1
2
app.archs['iPhoneOS'] << 'arm64'
app.archs['iPhoneSimulator'] << 'x86_64'

これで

1
2
rake clean
rake

とすれば、ターゲットが追加されます。

ところがどっこい。

RubyMotion 2.38 までで開発ターゲットをiPadにしている場合、 iOS Simulatorが64bitモードで起動しない というバグがありました。

どうやら、app.archs['iPhoneSimulator'] << 'x86_64' としても、app.archs 内に x86 が入っている限り、iOS Simulator が32bitモードで起動してしまうようです。

困り果ててTwitterで呟いたところ、RubyMotionのContributorの方が丁寧に教えてくれました。

そのため、iOS Simulatorの起動を64bitモードで起動するために環境変数の指定を追加する必要があります。

1
2
3
app.archs['iPhoneOS'] << 'arm64'
app.archs['iPhoneSimulator'] << 'x86_64'
ENV['device_name'] = 'iPad Air'

ただし、この不具合は最新のRubyMotion 3.0では(@watson1978さんの修正により) Fixされているようです。

64bit対応② ポインタを使用している箇所で不具合が起きないか確認する

今回私が直面したのは、UIGraphics/CGContext でポインタを使った処理でのこと。

1
2
3
4
5
6
7
8
9
10
11
12
# 点線を引く!
context = UIGraphicsGetCurrentContext()
UIColor.blackColor.setStroke
CGContextSetLineWidth(context, 1)
lengths = Pointer.new(:float, 2) # :float
lengths[0] = 2
lengths[1] = 1
CGContextSetLineDash(context, 0.0, lengths, 2)

CGContextMoveToPoint(context, 100, 100)
CGContextAddLineToPoint(context, 200, 200)
CGContextStrokePath(context)

CGFloatは、32bit環境では32bit小数点数、64bit環境では64bit小数点数となっているため、 64bit環境でこいつを動かすと、CGContextSetLineDash(context, 0.0, lengths, 2) のところでコケます。

64bit環境に対応するためには、Pointerが指すオブジェクトの型をdoubleにしてやる必要があります。

1
lengths = Pointer.new(:double, 2) # :double

どうしても64bitと32bitを両立させたい!という場合(そんなのあるのか?)は、この両者を並立させることもできます。 こちらも件の@watson1978さんから情報をいただきました。

つまり、先の例で言えば

1
2
CGFloat_Type = CGSize.type[/(f|d)/]
lengths = Pointer.new(CGFloat_Type, 2) # :float/:double

こんな感じですね。

さいごに

RubyMotionでの64bit環境対応はそう難しくはありません。 今回のような事態に巻き込まれることも極稀にあるようですが・・・。 Appleの設けた来年2月までの期限に向けて、早々に取り掛かってみるのも悪く無いと思います。

ともあれ、今回のトラブルで丁寧にご対応くださった上、この記事への引用をご了承くださった @watson1978様には厚く御礼申し上げます。

この記事を書いた人kyoh

kyohです。蕎麦と鳥をこよなく愛するおでぶです。C#使いでした。

waculでは、プログラマを募集しています。

現在はプロダクトとして、課題発見から改善提案まで自動で行うWeb改善プラットフォーム「AIアナリスト」を開発中です。

waculの採用情報へ

ページトップへ