[iOS] アプリ開発日記

2016/05/1

こんにちは。きんくまです。

以前に次のアプリ作りますとかって、ブログにちらっと書きました
>> [iOS] Zippy電卓アップデート予告とか中間報告とか次回作とか

それから2ヶ月。何もしていなかったかと思いきや、珍しく少しずつ進めております。

・アプリ名を決めた
・アプリアイコン作った(けど、もう一回作り直すかも)
・機能の仕様を固めた
・画面のワイヤー、遷移方法などを固めた
・UI上作れるか部分的なモックを作ってテスト
・アプリ内課金やったことなかったのでテスト
・データベース(SQLite)まわりのモデルのプログラム作成
・DBまわりのユニットテストも同時に通した

「軽めのアプリにしてサクッと出そう!」としてたんですが、「せっかくやるならこの機能入れたいなー」とかやってたら思ったより時間がかかっちゃいましたw

モデルまわり

一番肝心かなめのモデルまわりのプログラムがしっかり作れたので、あとはなんとかなるかなと。(なるといいな)
ずっと前に読んだアルゴリズムとデータ構造の本に書いてあったんだけど、

・アルゴリズムをいくら改良しても、悪いデータ構造だとうまくいかない
・逆に良いデータ構造ならば、多少アルゴリズムが悪くても問題ない

みたいなことが書いてあって、それ以来何かプログラムを書くときは、コアになるデータ構造だけはしっかり作るように心がけています。
画面の見た目や操作方法はあとから変えやすいけど、データ部分は後からだとどうしても変更が難しいですしね。

それでこれから、ユーザーが直接さわる画面操作部分(UI)のプログラムを書いていくところです。

プログラムの進め方

他の人がどうやってアプリを作っているのかわからないのだけれど、自分の場合はこんな感じに進めてます。

1. とにかく動作するアプリを常においておく(各画面は空でもOK)
2. 各機能ごとに別プロジェクトを作る。(gitでbranch切るとかじゃなくて完全に別プロジェクト)
  実験したり、実際に機能を作り込む
3. 別プロジェクトでうまくいったら、それを本体に移植
4. 2と3を繰り返して本体に機能が追加されていく

1回やったことのあるUIだったり機能の場合は、2と3はとばして直接本体のコードに書いていきます。

この進め方のメリットとしては、
・本体はきれいなソースを保ちやすい(実験したりしたときの後が残らない)
・別の案件で、ある機能が必要になったときに機能別プロジェクトとして保存してあるので移植しやすい

私の場合、記憶力が悪いのですぐ忘れてしまうんですよね、、。で、このやり方ってどうやるんだっけ?といって単体機能のプロジェクトを見てやり方を思い出す感じです。

というわけで、新しいアプリがもう少し進んだらどんなアプリかお知らせできそうです。
よろしくお願いします m(_ _)m

LINEで送る
Pocket

[Terminal] Macでターミナルから複数サイズのアイコン画像を一括変換して作成するシェルスクリプト

2016/04/26

こんにちは。きんくまです。

iOSアプリだとアイコン画像を作るのにIconKitを使っています。
ただ、いまAIRアプリ用にアイコンを作成したくなりました。IconKitはAIR用でないので、なんとかしないといけません。

以前にどこかのブログでmacだとコマンドから画像処理をできると書いてあったことを思い出しました。
調べてみると、こんな感じにsipsコマンドで変更できるようです。
便利ですね。

>> Batch Resize Images Quickly in the OS X Terminal
>> 画像ファイルを操作する(sips)

シェルスクリプト

一括変換するシェルスクリプトを作成しました。

#!/bin/sh

# settings ============

ICON_FILE="sample_icon"
ICON_FORMAT="png"
OUTPUT_ICON_DIR="icons"
OUTPUT_ICON_NAME="icon"
ICON_SIZES=(16 32 48 128)

# ====================

if [ -d "./${OUTPUT_ICON_DIR}" ]
    then
        echo ""
    else
        mkdir "./${OUTPUT_ICON_DIR}"
fi

for size in ${ICON_SIZES[@]}
do
    sips -Z ${size} "${ICON_FILE}.${ICON_FORMAT}" --out "./${OUTPUT_ICON_DIR}/${OUTPUT_ICON_NAME}${size}.${ICON_FORMAT}"
done

設定の説明

元のアイコンファイル名(拡張子前)
ICON_FILE=”sample_icon”

元のアイコン拡張子
ICON_FORMAT=”png”

出力先ディレクトリ名(なければ1つ下の階層に新規作成)
OUTPUT_ICON_DIR=”icons”

出力ファイル名
OUTPUT_ICON_NAME=”icon”

出力サイズ(スペースでサイズを区切る。例の場合は 16px, 32px, 48px, 128px を作成)
ICON_SIZES=(16 32 48 128)

この投稿の続きを読む »

LINEで送る
Pocket

[iOS swift] ContainerViewをプログラムで作りたい

2016/04/25

こんにちは。きんくまです。

今回はContainerViewです。
ContainerViewを使うと親子関係を持つViewControllerをInterface Builder上で簡単に設定できます。

こういうUIのやつ

containerView1

IB上ではこう表示されます。

containerView2

ただ、IB上でこのように設定してしまうと、子供側のStoryboardの再利用が難しい気がしました。
基本的にStoryboardは分割しておいた方が管理が楽なので、子供は子供だけのStoryboardファイルにして、それを親側に埋め込みたいです。
それで、いろいろと試行錯誤していて、なんとかわかったのでまとめておこうかと。

詳しいことはAppleさんのドキュメントを見てください。
>> Implementing a Container View Controller

StoryboardではContainerViewは使わずにUIViewを使う

この投稿の続きを読む »

LINEで送る
Pocket

[iOS swift] swift演算子の ?? って何?

2016/04/12

こんにちは。きんくまです。
今回は小ネタです。

サンプルプロジェクトを作ってみたら ?? 演算子があったので何かなと思って調べてみました。

Appleさんの公式
>> Nil Coalescing Operator

coalesce という単語がわかんなかったので、調べたら 「結合する」とか書いてあるので、直訳すると「nil結合演算子」でしょうか? とりあえず名前はおいておいて。

で、どういうのかというと、こんな感じにデフォルトの値を入れるときに便利みたいです。JavaScriptの || みたいな感じ?

let a:Int = 5
var b:Int?

let c:Int = b ?? a
print("\(c)") //5

これはこういう三項演算子の短縮系だそうです。

let a:Int = 5
var b:Int?

let d:Int = b != nil ? b! : a

if文を使ってかけばこうなりますね。

let a:Int = 5
var b:Int?

var e:Int
if b != nil {
    e = b!
}else{
    e = a
}
print("\(e)")

関数の引数チェックに

引数がnilだったらデフォルトの値を入れてみる。

func greeting(message:String?) -> String {
    let myMessage:String = message ?? "Hello"
    return myMessage + " world"
}

でもこうしなくてもデフォルト引数がかけるので、上のはこうも書けるのかなと思って書いてみた。

この投稿の続きを読む »

LINEで送る
Pocket

[iOS] swift2でもエラーハンドリングしたい NSError, do catch

2016/04/2

こんにちは。きんくまです。

ブログのアクセスログを読むと、iOSのエラーハンドリングの記事がそこそこアクセスがあります。
ただ、この書き方だとswift2だと動かないので申し訳なく思いまして。なのでswift2版を書いておこうかと。
2番目の記事のエラーと例外のところはswiftでも考え方は同じなので役に立つかと思われます。

>> [iOS] swiftでもエラーハンドリングしたい!
>> [iOS] NSErrorでエラーハンドリングしたい

ちなみにこの文はAppleさんの公式のドキュメント見ながら書いているので、詳しくはそこを読んでいただければ。

>> The Swift Programming Language (Swift 2.2): Error Handling

手短に書き方だけ説明。do catch 構文

まずは使い方です。この構文を知っておけばとりあえずはなんとかなります。

do {
    try xxxxx()
} catch {
    print("error")
}

エラーの内容がしりたければこちら

do {
    try xxxxx()
} catch let error as NSError {
    print("error \(error)")
}

xxxxx のところで throws を返すかもしれないメソッドを呼び出してください。
こういうやつです。

func xxxxx() throws 

もしエラーがそこで投げられたら catch 構文が呼ばれます。

この投稿の続きを読む »

LINEで送る
Pocket

[iOS] SQLite.swiftを実機で立ち上げるとReason: image not found のエラーが出るとき

2016/03/25

こんにちは。きんくまです。

新しいアプリを作ろうといろいろと試しています。
それでデータベースはCoreDataをやめて、そのままのSQLiteの方が使いやすいんじゃないかと思ってそちらにしました。
CoreDataは前のアプリで使ってみたけど、無理して使う必要ないかなと。

それでSQLiteのライブラリを簡単に使おうと思って、利用しているのが SQLite.swift です。

使い方はマニュアルどうり進めればかんたんOK。Simulatorでもバッチリ動きます!
なんだけど、実機に入れたとたんエラーが出るよ!

dyld: Library not loaded: @rpath/SQLite.framework/SQLite
  Referenced from: /アプリのパス
  Reason: image not found

そんでCocoaPodsはプロジェクトファイルにスクリプトが埋め込まれて走るのがいやだったので使わず、マニュアルでインストール。
公式のマニュアル通りにインストールしたのにうまくいかない、、。

同じエラーで困っているのを発見して、同じようにやったけどうまくいかなかった。

いろいろと試したところ解決したのでメモ。

Xcode 7.2.1
SQLite.swift 0.9.2

まず、

1. General タブの Linked Frameworks and Libraries から SQLite.frameworkははずしてきれいな状態にする。
2. FinderでSQlite.swiftのプロジェクトをドラッグ&ドロップでプロジェクトに追加

sqlite_swift1

次が重要ていうかこれだけ

3. General タブの Embedded Binaries からSQLite.frameworkiOSを選ぶ
4. ClearnしてからBuild

これだけで、Linked Frameworks and Libraries にも追加されまする

sqlite_swift2

依存関係も自動設定されまする

sqlite_swift3

参考)外部フレームワークについての記述。これ見てできました!すばらしい
>> iOS app with framework crashed on device, dyld: Library not loaded, Xcode 6 Beta

いちおう先を見越してArciveもためしてみたけどエラーが出てないから大丈夫なんじゃないかと。

LINEで送る
Pocket

[iOS swift] Doubleとか小数の浮動小数点の誤差をなくしたい NSDecimalNumber

2016/03/8

こんにちは。きんくまです。

電卓アプリのZippy電卓を作っていて浮動小数点の誤差が出ることに気がつきました。

例えばこんな計算をやってみます。

2.35 – 2.34 = 0.01 になるはずです。

let n1:Double = 2.35
let n2:Double = 2.34
let n3:Double = n1 - n2
print("\(n3)")

これの出力結果はなんと、、、、

0.0100000000000002

という数値が出ます。
これはたぶんなんですが、小数を表すときに内部的に誤差が出てしまうからだとおもいます。

で、これを防ぐのにはNSDecimalNumberを使います。

let d1:NSDecimalNumber = NSDecimalNumber(double: 2.35)
let d2:NSDecimalNumber = NSDecimalNumber(double: 2.34)
let d3:NSDecimalNumber = d1.decimalNumberBySubtracting(d2)
print("\(d3.stringValue)") //0.01

端数処理でつまった

それで、ここまではOKだったのですが、先日つけた端数処理(丸め)機能でつまりました。

この投稿の続きを読む »

LINEで送る
Pocket

ページトップへ戻る