iOS実験専用アプリを作って活用する話の続きです。前回は、簡単な機能の実験を取り上げました。続きとして、もう少し複雑な機能を作るときの注意点を解説します。今回のswiftコードも、一部を除いてViewControllerクラスに入れます。
各ボタンに用意してある2つの関数のうち、多くのコードを追加するのは、タップされたときに動かすほうの関数(名前がtestで始まる関数)です。行数が多くなると困るのが、機能をオフする場合。全体を囲むコメントで何とかなりますが、2カ所の入力が必要で、使いやすくはありません。やっぱり、オフする際には1行だけコメントに切り替える方法(2つの半角スラッシュ)が一番です。
1行だけでオンオフする方法としては、return文を追加する手も使えます。実行したいコードの先頭にreturn文を入れ、それをコメントにすると以降が実行されるという具合に。逆に、return文をコメントでなくすると、オフの状態という使い方です。ただし、return文が使える状態では、コンパイラーから注意が出てしまいます。return文以降が絶対に実行されないよ、という注意で、例の黄色い表示です。気分が良くないので、使いたくないのが普通でしょう。
これらとは違う方法を採用します。ボタンに追加する機能が2行以上になるときには、それ全体を関数として外に出します。ボタンのタップで起動する関数内では、外に出した関数を呼び出す形にします。こうすると、呼び出す部分が1行になり、、機能のオンオフが簡単になります。具体的なswiftコードは、機能をオフした状態では次のようになります。
// ボタンタップで動作する機能を関数として外に出し、それをオフした状態
// ====================================== ボタン15
func startBtn15F() {
aryButton[15].setTitle("x総数計算", forState: .Normal)
}
func testBtn15F(rSender:UIButton) {
setMsgF(1, "タップ15")
//run15F() // <------------------------ コメントにしてオフ状態
}
func run15F() {
...
getTotal15F()
...
}
func getTotal15F() {
...
}
// ====================================== ボタン16
ここで大事なのは、追加した関数名です。他の機能と関数名が重複しないように、関数名の一部にボタン番号を必ず入れます。ボタン15に追加する機能の場合なら、関数名を「run15F」や「getTotal15F」にするといった具合に。このようにルール化しておけば、関数名の重複を気にする必要がなくなります。
もちろん、例外もあります。作り終わったとき、関数をそのまま持っていけるように作りたい場合もあるでしょう。そんなときは、最終的に使う関数名を付ます。当然、関数名が重複しないように注意しながらですが。
作る機能が複雑になるほど、関数の外に変数を用意する必要性が増します。変数を使う場合も、簡単な注意点があります。まず変数名ですが、関数名と同じように、ボタン番号を必ず含めます。このルールに決めると、変数名の重複を気にする必要がなくなります。
次に変数宣言の挿入場所です。追加する機能だけで使う変数ですから、関係する関数の近くが最適です。これも自分なりのルールを決めたほうがよいでしょう。私の場合は、最初に用意された2つの関数よりも前に置くと決めています。最初に変数宣言があれば「この機能は、関数の外に出した変数を使っている」と気付きやすくなるからです。とにかく、自分の好みのルールで統一することが大事です。
私のルールで作った場合の具体的なswiftコードは、次のようになります。
// 関数の外で変数を使う場合の例
// ====================================== ボタン16
var iAVPlayer16:AVAudioPlayer!
func startBtn16F() {
aryButton[16].setTitle("AIFF再生", forState: .Normal)
}
func testBtn16F(rSender:UIButton) {
setMsgF(1, "タップ16")
iAVPlayer16 = playSoundResF("Yen", "aiff", 1.0)
iAVPlayer16.play()
}
func playSoundResF(rFName:String, _ rSuffix:String, _ rVol:Float) -> AVAudioPlayer {
var iAVPlayer:AVAudioPlayer!
let fileURL:NSURL = NSBundle.mainBundle().URLForResource(rFName, withExtension:rSuffix)!
iAVPlayer = AVAudioPlayer(contentsOfURL:fileURL, error:nil)
iAVPlayer.volume = rVol
return iAVPlayer
}
// ====================================== ボタン17
この例のtestBtn16F関数では、コメント化する場合の対象が2行になっています。連続した2行ならコメントに変更しやすいので、わざと残してみました。実験専用アプリですから、ある程度までなら、緩く作っても構わないと思います。
画面上にUI部品を追加し、それに値を入れたり参照する場合も、関数の外に出します。置き場所は、変数と同じルールで構わないでしょう。具体的なSwiftコードは、次のようになります。
// UI部品(ここではUITextField)を追加する例
// ====================================== ボタン17
var txfTimeIntv:UITextField!
func startBtn17F() {
aryButton[17].setTitle("HandCtrl", forState: .Normal) // <----- ボタン名変更もお忘れなく
txfTimeIntv = createTxtFldF("12", 16, ALIGN_LEFT, 700, 60, 100, 30)
viewBase.addSubview(txfTimeIntv!) // <--------- オフするときは、この行をコメント化
}
func testBtn17F(rSender:UIButton) {
setMsgF(1, "タップ17")
run17F() // <--------- オフするときは、当然ですが、こちらもコメント化
}
func run17F() {
...
let iDouble:Double = Double(txfTimeIntv!.text!.toInt()!)
...
}
// ====================================== ボタン18
画面上にUI部品を追加した場合も、機能をオフしたいときがあります。そのときは、UI部品の生成はそのままにしておき、ビューに加えている箇所だけコメントにします。具体的には、addSubviewメソッドの箇所だけコメント化するということです。
この方法の利点は、続くコードへの影響がほとんどないことです。UI部品を生成して設定するところまでは残っていますから、そのUI部品を使うコードがコンパイルエラーになることはありません。
作りたい機能が大きくなると、独立したクラスとして作る場合もあるでしょう。その際には、追加するクラスを別なswiftソースコードに入れ、そのクラスを利用するコードだけをViewControllerクラスに入れます。
// クラスを使う側のコード(ViewController.swift)
// ====================================== ボタン18
func startBtn18F() {
aryButton[18].setTitle("HandCtrl", forState: .Normal)
}
func testBtn18F(rSender:UIButton) {
setMsgF(1, "タップ18")
run18F()
}
func run18F() {
let handCtrl = HandController()
...
}
// ====================================== ボタン19
// クラスは別なソースコードに分けて追加(HandController.swift)
class HandController {
...
}
クラスとして作る場合は、重複しないクラス名を付けるはずですから、ボタン番号を気にしないで付けても大丈夫でしょう。そのクラスを呼び出す関数だけ、ボタン番号を付けることになります。
続いて、デバッグ時に役立つ使い方も紹介しましょう。期待したとおりに動かない場合は、どこを通っているか調べたり、途中での値を表示したり、プログラムが動く様子を探ろうとするでしょう。ブレークポイントを設定して動き止め、途中の状態を調べる方法も、よく使われます。
それとは別に、println文を使って、動きの流れを記録したり、途中の変数を記録する方法もあります。println文で出力した内容は、デバッガで見ることになるため、画面の切り替えが生じます。少し手間ですね。その代わりに使うのが、用意したラベルへのメッセージ表示です。setMsgF関数とaddMsgF関数を組み合わせて、通った箇所を表示させます。
具体的な例を見たほうが分かりやすいでしょう。次のようなswiftコードになります。
//
// ====================================== ボタン20
func startBtn20F() {
aryButton[20].setTitle("HandCtrl", forState: .Normal)
}
func testBtn20F(rSender: UIButton) {
setMsgF(1, "タップ20")
run20F()
}
func run20F() {
setMsgF(0, "通過:0,")
...
if flagVX {
addMsgF(0, "2b,")
...
return
}
addMsgF(0, "2a,")
...
addMsgF(0, "4,")
...
switch (n) {
case 1:
addMsgF(0, "61,")
...
case 2:
addMsgF(0, "62,")
...
case 3:
addMsgF(0, "63,")
...
default:
addMsgF(0, "69,")
...
}
...
addMsgF(0, "9,")
}
// ====================================== ボタン21
かなり入れ過ぎですね。何種類かの例を含めたので入れ過ぎました。実際に使う場合は、適度な数を入れてください。
使い方の基本としては、最初にsetMsgF関数を使い、前の実行で残っている文字列を消しながら、新しい文字列を入れます。それ以降ではaddMsgF関数を使い、文字列を後ろに追加していきます。if文やswitch文のところでは、両方または見たいほうにaddMsgF関数を付けて、どちらに行ったのかを調べます。タップした直後に、動きがラベルに表示されるので、表示を切り替える必要はありません。もしテキスト入力欄を追加し、そこに文字列を入力してはタップするようなテストだと、値によって通る箇所の違いが容易に見えて助かります。
ちなみに、最初に表示するsetMsgF関数にだけ、先頭に「通過」という文字列を入れています。これは、何年後かにソースコードを見たときや動かしてみたとき、「通過した箇所を表示しているのだな」と理解させるためです。「少しの手間で、数年後の自分へ親切にする」という方針の一環です。
デバッグ時の途中の値の表示も、同様に簡単です。表示するラベル番号を選び、setMsgF関数やaddMsgF関数を追加するだけです。
// 実行途中の値もラベルに表示
...
setMsgF(4, "iStr=\(iStr)")
...
if (n > 5) { addMsgF(4, ",iStr2=\(iStr2)") }
...
値の表示でも、できるだけ1行で書くことが大事です。1行だけだと、先頭に「//」を追加してコメントに変更しやすいですから。
私の場合、コメント化した行は、使い終わっても残すようにしています。後から機能を変更したり、再テストするときに、その行が役立つこともあるからです。本番用のソースコードではないので、コードを綺麗に保つ必要はないでしょう。
ここまで、実験専用アプリの使い方を詳しく説明しました。いろいろな注意点も細かく取り上げたので、すべて理解すれば、かなりの使い手になると思います。次の投稿では、書き残した点などを書く予定です。
(使用開発ツール:Xcode 6.0.1, SDK iOS 8.0)
0 件のコメント:
コメントを投稿