どうも、最近釣りにはまっている松山事務所の石丸です。
今回は第4回までで学んだ機能をフルに使ってメモアプリを作ってみます。
まだ画面遷移の方法を学んでいないので1画面にすべての機能を詰め込みます。
スマホアプリらしくないのですが、今はこれが精一杯。
開発環境はOS X Yosemite(ver10.10.5)、Xcode(ver7.0)になります。
レイアウト
いつも通り iOSの Single View Applicationプロジェクトを作成したら、次のようにコントロールを配置していきます。
アプリの仕様として、TextFieldにメモを入力してreturn(改行)または確定ボタンでTableViewにメモを追加。TableViewでメモを選択すると編集モードになり、選択したメモの内容がTextFieldで編集できます。
第1回から Label、第2回から Button、第3回から TableView、第4回から TextFieldとオールスターですね。
さらに第4回同様それぞれのコントロールに Pinを設定して位置ずれしないようにします。各コントロールの Pin設定は次のようになります。
Labelと Buttonは固定幅でそれぞれ画面端にくっつけて、余った幅が TextField に割り当てられるよう TextField は Labelと Buttonとの距離だけを設定します。TableView には、画面上部のコントロールとの距離を設定し、左右と下は画面端にくっつけます。
以上でレイアウトが完成です。
Outlet
次はアシスタントエディタでコントロールをプログラムに関連付けていきます。
Main.storyboard を選択してアシスタントエディタに切り替えたら、各コントロールに Outletを設定していきます。
今回は数が多いので設定後の接続情報ダイアログだけを載せます。(設定の仕方は第2回〜第4回を参考にしてください)
TextField は入力されたメモを取得したり、メモ一覧で選択されたメモを表示したりするために、editMemoField という名前でプログラムから制御できるように Outletを設定します。さらに、第4回同様に return(改行)で確定ボタン押下と同じ動作をさせるために delegateを接続します。
Buttonはメモの入力を確定させるトリガーになればいいだけなので、タップの Actionだけを設定します。
TableView は追加・修正されたメモを反映させるため、memoListView という名前でプログラムから制御できるように Outletを設定します。また、dataSource、delegate も接続します。
ViewController 側から見るとこんな感じになります。
実装
ViewController.swift は次のようになりました。
流石に今回は少し長いですね。
import UIKit private let unselectedRow = -1 class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate { @IBOutlet weak var editMemoField: UITextField! @IBOutlet weak var memoListView: UITableView! var memoList: [String] = [] var editRow: Int = unselectedRow override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. memoListView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell") editMemoField.becomeFirstResponder() } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } @IBAction func tapSubmitButton(sender: UIButton) { applyMemo() } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return memoList.count } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) if indexPath.row >= memoList.count { return cell } cell.textLabel?.text = memoList[indexPath.row] return cell } func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { if indexPath.row >= memoList.count { return } editRow = indexPath.row editMemoField.text = memoList[editRow] } func textFieldShouldReturn(textField: UITextField) -> Bool { applyMemo() return true } func applyMemo() { if editMemoField.text == nil { return } if editRow == unselectedRow { memoList.append(editMemoField.text!) } else { memoList[editRow] = editMemoField.text! } editMemoField.text = "" editRow = unselectedRow memoListView.reloadData() } }
5行目:クラス定義に UITableViewDelegate , UITableViewDataSource , UITextFieldDelegate プロトコルを追加。
9〜10行目:メモした内容を保持しておくString 配列 memoList と編集中の行番号を保持する editRow をメンバ変数として定義。
15行目:メモ一覧で表示するセルを識別するIDの登録処理を追加。
24〜26行目:確定ボタンがタップされたイベントでは、入力されたメモをメモ一覧へ反映するメソッドを呼び出すように実装。
32〜40行目:メモ一覧が表示する内容を返すメソッドでは9行目で宣言した memoList が保持している行番号に対応したメモを返すように実装。一応保持しているメモの数を超えていないことをチェック。
42〜48行目:メモ一覧のセルが選択されたイベントでは、選択されたメモを TextField に設定し、選択された行番号を10行目で宣言した editRow に保持。
50〜53行目:TextFieldで return(改行) されたイベントでは確定ボタンタップイベントと同様に、入力されたメモをメモ一覧へ反映するメソッドを呼び出すように実装。
55〜68行目:メモの入力を確定するメソッドでは、追加モードか編集モードかを判定し、9行目で宣言した memoList に対して入力テキストの追加、または上書きを行い、 TextField の内容のクリア、編集モードから追加モードへの変更、メモ一覧の更新を行うように実装。
実行
さて今回は多少動きがあります。起動時はメモ一覧になにもない状態なので、どんどんメモを追加していきます。
追加したメモを編集したい場合は、メモ一覧から編集したい行を選択します。
選択した行の内容が入力エリアに表示されるので、内容を編集して確定ボタンを押します。
iPhoneのメモアプリはメイン画面にメモ一覧があって、追加、編集の際には専用の画面に遷移しますよね。
今回のメモアプリにこれ以上の機能を追加するとなった場合、流石に1画面では限界があるので、画面遷移の方法を学びたいと思います。が、その前にこのアプリ。終了するとメモの内容を忘れてしまうんですよね。。。
データの保存の方法を学ぶのが先でしょうか。
今回はここまで。
ありがとうございました!