2015年11月17日火曜日

【Xcode / Swift入門】簡単なToDoリストアプリを作ってみよう

本稿では、Swift2.0を用いてToDoリストを作ってみたいと思います。 
※以前に記載したTableView、Segue、データの保存方法を使用するため、もし前記事をご覧になられていない方は、下記をご参照ください。
 3-1. TableViewを使ってみよう
 3-2. Segueを使ってみよう
 3-3. データを保存してみよう

今回のToDoListの目標は、下図のようにToDoアイテムの追加、リスト表示、削除、更新ができることを目指します。また、アプリを落としてもデータが保存されている(データが消えない)ように設定もします。






アプリの見た目(Main.storyboard)の設定

では、アプリの見た目を作成するために、Main.storyboardを設定していきます。
まず始めに、プロジェクトを作成します。Xcodeを開いて、
Create a new Xcode project → Single View Application → product name を”ToDoList”としてCreateボタン
を押します。プロジェクトが作成されましたら、Main.storyboadを開きます。
まずは、ToDoアイテムを表示するリスト画面を作成するために、View ControllerにTableView及びNavigationBarを配置します。

ユーティリティエリアよりTableViewを選択し、View Controllerにドラッグ&ドロップします。合わせて、セルを一つ追加(Prototype Cellsを"1"に)しておきます。


次に、追加したセルを選択し、Identifierを"cell"とします。


最後に、TableViewをControlを押しながら、View Controllerへドラッグ&ドロップし、"dataSource"と"delegate"をチェックしましょう。これでTableViewの使用が可能になります。
※この辺りの詳細は、「3-1. TableViewを使ってみよう」にて解説しています。



次に、NavigationBarの設定です。ユーティリティエリアよりNavigationBarをViewControllerへドラッグ&ドロップし、追加したNavigationBarにBarButtonItemをドラッグ&ドロップします。合わせてBarButtonItemのSystem Itemを"Add"に変更し、追加を表す”+”マークに変更しておきましょう。


以上で、ToDoリストを表示する画面の設定は完了です。

次に、アイテムを追加する画面を設定していきます。ユーティリティエリアよりViewControllerをドラッグ&ドロップし、ViewController(画面)を追加します。合わせて、画面サイズも変更しておきましょう。



では、追加したViewControllerに下図のようにNavigationBar、BarButtonItem(戻る)、TextField、Buttonを作成しましょう。



以上で、アイテムを追加する画面の作成は完了です。

では、見た目(Main.storyboard)の設定の最後にSegueを設定します。ToDoList画面の"+"を押下するとアイテム追加画面へ、アイテム追加画面の戻るを押下するとToDoList画面へ遷移するよう設定します。

"+"ボタンをControlを押しながらアイテム追加画面へドラッグ&ドロップし、Showを選択します。


同様に、"戻る"ボタンをControlを押しながらToDoList画面へドラッグ&ドロップし、Showを選択します。下図のように表示されていれば成功です。



ここで、一旦ビルドして画面がちゃんと表示されていること、画面遷移できることを確認します。そこまで出来れば、画面の設定は完了です。次はソースコードを記述(実装)していきます。


ToDoアイテム追加画面の実装

まず初めに、ToDoListへアイテムを追加する画面の実装を行います。
この画面では、
・テキストフィールドに入力された文字列をAddボタンが押下されたら保存する
・保存するにあたっては、NSUserDefaultsを使用
・キーボード以外をタッチするとキーボードが下がる
・キーボードのreturnを押下すると、キーボードが下がる
という機能を実装します。

まずは、ソースコードを記述するSwiftファイルを作成します。
File→New→File...を選択し、CocoaTouchClassを選択します。


Nextボタンを押し、
Class:AddToDo
Subclass of:UiIViewController
Language:Swift
を選択し、Nextボタンを押します。

そうするとAddToDo.swiftというファイルができると思います。

次に、これをMain.storyboardで作成したViewから使用できる設定をします。
Main.stoyboadを開いて、アイテムを追加する画面の左上のボタンを選択肢、Custom ClassにAddToDoと記述します。こうすることにより、このViewとAddToDo.swiftが関連付けられたことになります。




次に、テキストフィールドに入力された文字列をAddボタンが押下されたら保存する機能を実装します。

出来上がったAddToDo.swiftにMain.storyboadから変数を追加します。
テキストフィールドをcontrolを押しながらソースコードの画面にドラッグ&ドロップし、Connectionがoutletになっていることを確認し、適当に名前をつけます(例では、itemTextとしています)。次に、Addボタンも同様にcontrolを押しながらソースコードの画面にドラッグ&ドロップし、ConnectionをActionに変更し適用に名前をつけます(例では、addItemとしています)。







変数の準備ができたら、import UIKit直下に

var todoItem = [String]()

と記述します。これは、ToDoアイテムを一旦保存するためのString型の配列で、クラス(ファイル)を跨って使用するため、 classの前(import UIKit直下)に記載します。

次に、ボタンをクリックされた際にNSUserDefaultsにテキストフィールドの値を保存するよう記述します。テキストフィールドの値をString型の配列todoItemに格納し、NSUserDefaultsにSetします。合わせて、テキストフィールド内の文字列は、空欄にします。

    
@IBAction func addItem(sender: AnyObject) {
        todoItem.append(itemText.text!)
        itemText.text = ""
        NSUserDefaults.standardUserDefaults().setObject(todoItem, forKey: "todoList")
}


次に、キーボード以外をタッチするとキーボードが下がる機能です。class AddToDo: UIViewController 内に以下を記述します。これは、決まり文句みたいなものです。

 
 override func touchesBegan(touches: Set, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }
 

最後に、キーボードのreturnを押下すると、キーボードが下がる機能です。class AddToDo: UIViewController 内に以下を記述します。こちらも決まり文句みたいなものです。
 
    func textFieldShouldReturn(textField: UITextField!) -> Bool {        
        itemText.resignFirstResponder()        
        return true        
    }

これで、アイテムを追加する画面の実装は完了です。次にToDoList画面を実装していきます。


ToDoList画面の実装

次に、追加したToDoアイテムのリストを表示する画面を実装していきます。
この画面では、
・NSUserDefaultsに保存されているアイテムの取得、表示
・NSUserDefaultsに保存されているアイテムをスライドして削除
・テーブル(リスト)を下に引っ張って更新
する機能を実装したいと思います。


NSUserDefaultsに保存されているアイテムの取得、表示機能を実装します。
この実装は、3-1. TableViewを使ってみように記載した通りの実装をします。詳細は、3-1をご参照ください。

まず初めにTableViewを取得するために、class名の後ろにUITableViewDelegateを追加します。

class ViewController: UIViewController,UITableViewDelegate {

次に、NSUserDefaultsの値を取得し、先ほどのAddToDo.swiftにて作成した配列型の変数todoItemに代入します。これは起動時に呼ばれる関数であるviewDidLoad()内に記述します。

   
override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        if NSUserDefaults.standardUserDefaults().objectForKey("todoList") != nil {
            todoItem = NSUserDefaults.standardUserDefaults().objectForKey("todoList") as! [String]         
        }
    }


次に、以下二つの関数を記述します。

一つ目は、Tableに表示する行数を指定する関数です。これは、先ほど記述したNSUserDefaultsの値が代入されている変数todoItemが保持している文字列の数をカウントします。

 
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return todoItem.count 
    }

2つ目は各行へ値を表示する関数です。NSUserDefaultsの値が代入されている変数todoItemが保持している文字列を各テーブルに表示していきます。

    
 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cellValue = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
        cellValue .textLabel?.text = todoItem[indexPath.row]
        return cellValue
    }

次に、NSUserDefaultsに保存されているアイテムをスライドして削除機能を記述します。まず初めに、TableViewを操作するためにMain.storyboadから変数を持ってきます。
TableViewをcontrolを押しながらソースコードの画面にドラッグ&ドロップし、Connectionがoutletになっていることを確認し、適当に名前をつけます(例では、todolistTableとしています)



次に、下記の関数を記述します。これはTableViewのcellをEdit(編集)したい場合に使用する関数です。今回は削除(delete)をするため、削除する場合は、関数内で UITableViewCellEditingStyle.Deleteを使用します。
また、配列から該当の値を削除するため、removeAtIndex()関数も利用します。削除後は、再度NSUserDefaultsに値をセットし、最後にTableView全体を更新します。TableViewの更新には、先ほど作成したTableViewの変数にreloadData()と記述します。

 
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
        if editingStyle == UITableViewCellEditingStyle.Delete{
            todoItem.removeAtIndex(indexPath.row)
            NSUserDefaults.standardUserDefaults().setObject(todoItem, forKey: "todoList") 
            todolistTable.reloadData()     
        }
    }


最後に、テーブル(リスト)を下に引っ張って更新機能を記述します。
これは決まり文句のようなもので、下記を記述します。
 
override func viewDidAppear(animated: Bool) {
        todolistTable.reloadData()
    }


ここまでできたらビルドして、アイテムの追加削除をしてみてください。以上で完成です。今回は初歩的なところまでの作成にしていますので、色々拡張してみてください。

では、以下にViewController.swiftとAddToDo.swiftの全コードを記述しておきます。

 
//
//  ViewController.swift
//  ToDoList
//
//  Created by mosho on 2015/11/01.
//  Copyright © 2015年 mosho. All rights reserved.
//

import UIKit

class ViewController: UIViewController,UITableViewDelegate {
    
    @IBOutlet weak var todolistTable: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        if NSUserDefaults.standardUserDefaults().objectForKey("todoList") != nil {
            todoItem = NSUserDefaults.standardUserDefaults().objectForKey("todoList") as! [String]
        }
    }
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return todoItem.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cellValue = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
        cellValue .textLabel?.text = todoItem[indexPath.row]
        return cellValue
    }
    
    
    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
        if editingStyle == UITableViewCellEditingStyle.Delete{
            todoItem.removeAtIndex(indexPath.row)
            NSUserDefaults.standardUserDefaults().setObject(todoItem, forKey: "todoList")
            todolistTable.reloadData()
        }
    }
    
    override func viewDidAppear(animated: Bool) {
        todolistTable.reloadData()
    }
    

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}


    
//
//  AddToDo.swift
//  ToDoList
//
//  Created by mosho on 2015/11/01.
//  Copyright © 2015年 mosho. All rights reserved.
//

import UIKit

var todoItem = [String]()

class AddToDo: UIViewController {
    
    @IBOutlet weak var itemText: UITextField!
    
    @IBAction func addItem(sender: AnyObject) {
        todoItem.append(itemText.text!)
        itemText.text = ""
        NSUserDefaults.standardUserDefaults().setObject(todoItem, forKey: "todoList")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    override func touchesBegan(touches: Set, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }
    
    func textFieldShouldReturn(textField: UITextField!) -> Bool {
        itemText.resignFirstResponder()
        return true
    }
}




また、今回作成したViewController.swiftAddToDo.swiftは各リンクから取得可能です。ご参考までに。

では、次回はMapKitの使い方について説明したいと思います。



1 件のコメント:

  1. 非常にわかりやすい記事で参考にさせていただいているのですが、本記事の「アプリの見た目の設定」項目の最後にあるよう一旦ビルドすると、TableViewのOutlets接続が原因でAppDelegateエラーになると思います。

    返信削除