2014年8月24日日曜日

iOSの数値型

iOSでの数値型について。何回かググり直しているので、まとめてみる。

数字型の設定可能範囲

TypeMinMax
Int8-128127
Int16-32,76832,767
Int32-2,147,483,6482,147,483,647
Int64-9,223,372,036,854,775,8089,223,372,036,854,775,807
UInt80255
UInt16065,535
UInt3204,294,967,295
UInt64018,446,744,073,709,551,615

Int32 は、32bitのintと明示的に指定している形。

浮動小数点型は、
float は、有効桁数7桁。
double は、有効桁数15桁。

ObjectiveCで使える便利な整数型

Type32bit64bit
NSIntegerintlong
CGFloatfloatdouble

整数型の場合はNSIntegerを、小数点型の場合はCGFloatを使うと、実行環境によって使用する型を判断してくれる。
32bit環境ではInt32、64bit環境ではInt64のサイズが演算するのに効率が良い (のですよね?)
なので、意識せずに効率のよいサイズを選んでくれるラッパー的な存在という認識。
int, float, doubleの実際のバイト数は後述。

処理系によって変わる対応バイト数

Typearm7arm64
int32bit32bit
long32bit64bit
float32bit32bit
double64bit64bit

arm7はiPhone5の32bitのアーキテクチャ。arm64はiPhone5sの64bitのアーキテクチャ。
ビルド時、どのアーキテクチャのバイナリを作るかの指定がある。

NSInteger では、int or long を切り替えてくれるのだが、arm7では実は intとlongは同じ32bit整数型だった。
しかし、arm64の場合、longは64bitになる。
結局以下の様になる感じ?
Type32bit/arm764bit/arm764bit/arm64
NSInteger32bit32bit64bit
CGFloat32bit64bit64bit

Swiftの数字型

Type32bit64bit
IntInt32Int64
UIntUInt32UInt64
Float32bit32bit
Double64bit64bit
小数点がある数値の型推論は、デフォルトDoubleになるらしい。
CGFloatの中途半端な型でなくて、FloatとDoubleを用途に合わせてえらんでねという方式なのだと思う。
CGRectのwidthなどCGFloatだったり、NSIntegerなもののやりとりは、castしないとコンパイルエラーになってくれるので、 精度が大丈夫かを考えながらcastしていけばよさそう。

• • •

2014年8月22日金曜日

swiftのnullの扱い

WWDCで発表された新言語swift。
実際使ってアプリ作らないと分からない ということで、使い始めています。

ObjectiveCを使い始めた時に戸惑ったことの一つとして、
nullのものに対して処理を書いてもプログラムが落ちないということ。
また、違うクラス型にcastしてもプログラムが落ちないということ。
ここの部分、プログラムを落とすことができるようになっています。

変数の記述には、

(1) var name:String
(2) var name:String?
(3) var name:String!

の書き方があります。

(1) は、null は絶対設定されないのを保証する形式。
定数宣言時に var name:String = "abc"
と値を入れるか、初期化時(init)で値を入れる記述がないと、コンパイルエラーになります。もちろん、後でnull入れようとしてもコンパイルエラー。

(2)は、nullも入る可能性があるもの。
この場合、このオブジェクトに操作をするときは

name?.uppercaseString
のように ? をつける必要があります。
nameがnullだったとしても落ちません。

(3)は、初期化時はnullだけど、後でnull以外の何かが入る という時の形式。
たとえば、Storyboardで記述したUIオブジェクトをつなげているものとか。
この形式だと、
name.uppercaseString
..と?ナシで記述ができますが、もしnameがnullだったら落ちます。
nullを入れることもできます。

? で宣言している変数を、
name!.uppercaseString
と、!にすることも可能です。(Unwrap)

明確に、nullの可能性がある、無い というのがわかるので、
SDKも含め、他人のコードを呼び出すときにはとっても助かります。
(SDKのメソッドの引数は!が多い...)

自分のコードでも、
なぜ動かない? となった時、実はnullだった ということもよくあった。
違うクラス型にcastしてしまった時も、それに気づくのはcast時でなくてそのオブジェクトの変数やメソッドにアクセスした時にエラーで気づくので、どのタイミングでcast間違えた?と戻って考えないといけないこともあった。

なので、嬉しい反面、nullについては、ちょっと面倒だな と思うことも。

たとえば、UIは後回しでコードをざざっと書いてしまおう! という時。
「この変数は後でStoryboardからUI部品つなげるから、今はnullだけど、あとで繋ぐからいまはOK〜」 という感じでバーっと書くことがよくあった。

こんなとき、? で書けばよいのだろうけど、UIができた最終形では ! で書きたい。
開発途中の今は nullで落ちてほしくなけど、リリース時の最終形ではnullで落ちて欲しいという欲張りな要望です....

? で宣言すると、メソッドやプロパティアクセスする度に、?の記述が入るので、それらを後で削除するのが面倒。
! で宣言すると、開発途中だと落ちちゃうのでnullチェックのif文を入れる...としても、if文を後で削除するのも面倒。

開発途中だから暫定に入れたコードというのは消すのを忘れがちで、残ってしまうのはとっても嫌。バグの元になるし、後でコード見た時も混乱の元。
? や !は、最初から想定している指定で書くのがやっぱりいいと思う。
ということで、今、UIできていないところは、ガンガン落ちるプログラムで開発中です(笑)


• • •