2015年5月21日木曜日

iOS実験専用アプリを活用しよう(5)

かなり前になりますが、「iOS実験専用アプリ」の作り方と使いかたを紹介しました。今でも使い続けていますが、以前よりも使い方が上手になっています。というわけで、まだ公開していない新しい使い方を、続編として紹介します。

 

このアプリにはボタンが40個もあり、それぞれに別な機能を割り当てられます。割り当てられた機能の数が増えるほど、画面上に加えるUI部品の数も増えます。そのままでは使いづらいので、使い終わったボタンの機能は、オフする方法も紹介しました。ボタン名の最初に「x」を付けて、ボタンに割り当てた機能をコメント化する方法です。

この方法で問題なく使えるのですが、やはりオンオフが面倒だと感じるようになりました。オフした機能を使う際に、今使っている機能をオフすることも多く、切り替え作業は意外に面倒なのです。

というわけで、いちいちオフしなくても構わない作り方はないのかと、深く考えてみました。やはり真剣に考えると、思い付くものなのですね。今までよりも格段に良い作り方が、できてしまいました。

 

新しい作り方を紹介する前に、以前の作り方を簡単に説明します。

各ボタンには、2つの関数が用意されています。初期化の際に呼ばれるstartBtnXXF関数(XXは2桁の数字)と、ボタンをタップした時に呼ばれるtestBtnXXF関数(XXは2桁の数字)です。

通常の作り方は、初期化のstartBtnXXF関数でUI部品を表示し、ボタン用のtestBtnXXF関数で何かを実行するという形式でした。初期化の際にUI部品を表示してしまうため、複数のボタンをオンすると重ねて表示され、一緒にオンすることができなかったのです。

 

この問題を解決するために、少し発想を変えました。ボタン用のstartBtnXXF関数に初期化の処理も含めたら、オフする必要がないのではないかと。つまり、使い始めるまで何も表示させないという作り方です。

それとともに、使い終わったときの状態も考えなければなりません。使い終わってUI部品が表示されたままだと、別なボタンの機能を使う時に邪魔になります。そうならないようにと、画面上をクリアーする機能も、ボタンの機能に加えることにしました。

ただし、これらの機能を複数のボタンに割り当てたら、ボタンをどんどん消費してしまい、40個もあるボタンがすぐに足りなくなります。そこで、1つのボタンだけ使って、初期化からクリアーまでを実行できる方法を考えました。

解決策は簡単でした。タップされるたびに、順番に実行していけば良いのです。最初のタップで初期化だけします。次のタップでは、1つ目の使い方を実行します。さらに次のタップでは、2つ目の使い方を実行します。このように続けて、一番最後のタップにクリアー処理を割り当て、画面上のUI部品を消します。

クリアー処理が終わると、最初の状態に戻します。そのまま同じボタンをタップすれば、2回目の初期化処理が始まります。このように、初期化からクリアー処理まで何度も繰り返せるように作れば良いのです。

 

以上のような説明だと、難しそうに感じたかもしれませんが、実は意外なほど簡単です。具体的なSwiftコードを紹介しましょう。単純な例のほうが理解しやすいので、2種類の使い方しか含まない例を。

// ======================================== ボタン17:棒グラフ
var graphView17: GraphBarView!
var num17: Int = 0

func startBtn17F() {
    aryButton[17].setTitle("棒グラフ", forState: .Normal)
}
func testBtn17F(rSender:UIButton) {
    setMsgF(1, "タップ17")
    run17F()
}
func run17F() {
    switch num17 {
    case 0:
        setMsgF(2, "生成")
        graphView17 = GraphBarView()
        graphView17.setupF(10, 10, 600, 400)
        graphView17.setLabelF(["SEP 1","SEP 2","SEP 3","SEP 4","SEP 5","SEP 6","SEP 7"])
        graphView17.setDataF([1,24,12,18,30,10,21])
        graphView17.setDataRangeF(0, 40)
        viewBase.addSubview(graphView17)
        graphView17.drawGraphF()
        num17 = 1
    case 1:
        setMsgF(2, "正常1")
        graphView17.setLabelF(["NOV 1","NOV 2","NOV 3","NOV 4","NOV 5","NOV 6","NOV 7"])
        graphView17.setDataF([11,4,22,28,3,20,1])
        graphView17.setApparanceF(1)
        graphView17.drawGraphF()
        num17 = 2
    case 2:
        setMsgF(2, "正常2")
        graphView17.setLabelF(["SEP 1","SEP 2","SEP 3","SEP 4","SEP 5","SEP 6","SEP 7"])
        graphView17.setDataF([1,24,12,18,30,10,21])
        graphView17.setApparanceF(2)
        graphView17.drawGraphF()
        num17 = 999
    case 999:
        setMsgF(2, "終了")
        graphView17.removeFromSuperview()
        num17 = 0
    default:
        break
    }
}

見てのとおり、値ゼロで用意した変数num17を使って、順番に実行させているだけです。要点だけ簡単に説明します。

同じボタンを何度もタップするので、何の処理をしているのか画面上に示す必要があります。この例では、メッセージ欄に短い文字列を表示しています。最初が「生成」で、UI部品を画面上に表示させます。続く「正常1」は、正常系の1番目の実行です。この例には含まれてませんが、エラー系(エラーを含んだ処理)も後に付けるため、通常の使い方を「正常」と表示しています。次の「正常2」も正常系で、別な内容を実行します。最後の「終了」がクリアー処理で、画面上からUI部品を消し、変数num17を初期状態のゼロに戻します。

「終了」してしまうと、メッセージ欄の文字列を除いて、画面上には何も残りません。このボタンの機能を繰り返し実行しても構いませんし、別なボタンの機能を実行することもできます。他のボタンの機能を続いて試す場合は、「終了」で終わらせるのが基本的な使い方です。

 

実行させたい機能は、正常系だけではありません。ほとんどの機能にはエラー処理も含まれているので、正常系に続いて、エラー系の実行もボタンに含めます。前述の例にエラー系の実行を1つだけ加えたSwiftコードは、次のようになります。

// 前述のコードに、エラー系の実行を1つ加えたもの
func run17F() {
    switch num17 {
    case 0:
        setMsgF(2, "生成")
        graphView17 = GraphBarView()
        graphView17.setupF(10, 10, 600, 400)
        graphView17.setLabelF(["SEP 1","SEP 2","SEP 3","SEP 4","SEP 5","SEP 6","SEP 7"])
        graphView17.setDataF([1,24,12,18,30,10,21])
        graphView17.setDataRangeF(0, 40)
        viewBase.addSubview(graphView17)
        graphView17.drawGraphF()
        num17 = 1
    case 1:
        setMsgF(2, "正常1")
        graphView17.setLabelF(["NOV 1","NOV 2","NOV 3","NOV 4","NOV 5","NOV 6","NOV 7"])
        graphView17.setDataF([11,4,22,28,3,20,1])
        graphView17.setApparanceF(1)
        graphView17.drawGraphF()
        num17 = 2
    case 2:
        setMsgF(2, "正常2")
        graphView17.setLabelF(["SEP 1","SEP 2","SEP 3","SEP 4","SEP 5","SEP 6","SEP 7"])
        graphView17.setDataF([1,24,12,18,30,10,21])
        graphView17.setApparanceF(2)
        graphView17.drawGraphF()
        num17 = 101
    case 101:
        setMsgF(2, "エラー1")
        println("----------TEST-ERROR-1:Apparanceが範囲外")  // 区切り行
        graphView17.setLabelF(["NOV 1","NOV 2","NOV 3","NOV 4","NOV 5","NOV 6","NOV 7"])
        graphView17.setDataF([11,4,22,28,3,20,1])
        graphView17.setApparanceF(9)    // エラー
        graphView17.drawGraphF()
        num17 = 999
    case 999:
        setMsgF(2, "終了")
        graphView17.removeFromSuperview()
        num17 = 0
    default:
        break
    }
}

エラー系が正常系と違うのは、メッセージ欄に「エラー1」と出すだけではありません。続くprintln文で、エラーメッセージの区切り行を出力しています。区切り行には、発生が予想されるエラー内容を、短い言葉で書くのが基本です。

エラー系の実行では、処理内容に何らかのエラーを含めるため、実行対象の機能からエラーメッセージが表示されます。そのメッセージが、エラー系のどの実行で出されたメッセージなのか、判別できる必要があります。その判別を容易にするために、区切りのメッセージを出力するわけです。

区切り行だという点を強調するために、先頭にハイフン10個を付けています。エラーメッセージと一緒に並んだとき、区切り行として見えるようにとの配慮です。具体的には、次のように出力されます。

----------TEST-ERROR-1:Apparanceが範囲外
2015/05/20 20:24:50 ERROR:GBV_SA:Apparance番号が範囲外

これだけだと効果を実感できませんが、複数のエラー実行が並んでいて、1つの実行で複数のエラーメッセージが出力されたとき、区切り行のおかげで見やすく整います。

 

ちなみに、変数num17に設定する値ですが、単純な連番ではありません。この例では、正常系は1から始まり、エラー系は101から、終了は999にしてあります。このように作ってあるのは、正常系やエラー系の実行内容を追加したとき、変更する箇所を減らすためです。

もし最初から最後まで連番の場合、修正が大変になります。たとえば、正常系が15個、エラー系が20個あったとき、単純な連番だとエラー系は16番から始まります。そこへ。正常系の処理を1つ追加する場合、エラー系の開始番号が16番から17番へと変更になり、後に続く番号をすべて変えなければなりません。そんな無駄を避けるために、飛び飛びの番号をつけているのです。

この例では正常系の番号を1つずつ増やしていますが、2ずつ増やすとか、10ずつ増やすとかでも構いません。後から追加するとき、間に挿入しやすくなりますから。別な考え方として、正常系の実行を複数グループに分け、最初のグループは1番から始まり、次のグループは21番から、さらに次のグループは41番から、という形で番号を付ける方法もアリです。

 

今回は、「iOS実験専用アプリ」の上手な使い方として、機能をオフしなくて済むような作り方を紹介しました。

この方法が適さない機能もありますから、必要に応じて使い分けたり、別な新しい方法を考え出したりする必要があります。工夫して使うほど、iOS実験専用アプリはどんどん便利になりますね。私の場合、もはや必須ツールとなっています。

 

(使用開発ツール:Xcode 6.3.2, SDK iOS 8.3)

0 件のコメント:

コメントを投稿