ページ

2014年12月23日火曜日

[Obj-C, Swift] 設定部分の実装などを想定した NSUserDefaults を用いた値保持の基礎(後半)

【Obj-C, Swift】設定部分の実装などを想定した NSUserDefaults を用いた値保持の基礎(後半)

はじめに

前回の続きです。詳細は下記か目指す動作の項をご覧ください。

【Obj-C, Swift】設定部分の実装などを想定した NSUserDefaults を用いた値保持の基礎(前半)
 http://milanista224.blogspot.jp/2014/12/obj-c-nsuserdefaults-basic.html

前半は,Swift での実装です。やり方は何通りかあると思います。
例によって,
初級の方の役に立てばいいんですけど,個人的な趣味,備忘録なので気にしません!

目指す動作

主に設定の場面での実装を考慮している。

起動したら文字列と BOOL に関するラベルが 2 つ。初期値はそれぞれ"NO DATA"。
下部には Settings ボタンがあり,設定画面に遷移する。
設定画面ではテキストフィールドと UISwitch があり,
テキストフィールドに文字列を入力し,UISwitch もいじる。
Back ボタンを押し,遷移元の画面に戻ると設定画面で設定した文字列,BOOL 値に更新される。
これらの値は次回起動以降もリセットされることなくそのままであり続ける。

1 回作ってしまえば使いまわせるのでいいですね。(そんなたいそうなものではありませんが。)
Delegate を用いた値渡し(画面遷移)も近日やりたいですね。

実装

画像はクリックで RAW 画像見れます。見難いところあればお使いください。
Single View Application → プロジェクト名適当 → Swift
新しく ViewController を用意して下記画像のように部品をそれぞれ配置し,
Storyboard Segue Identifier 名(任意)をつける。(present modality)


次に File -> New -> File... -> Cocoa Touch Class で,
新たに SettingsViewController を SubClass:UIViewController で作成。


2 つ目の ViewCotroller のクラスにする。


Swift ファイルに直接コーディングしていきます。
ViewController.swift にはユーザデフォルトの値の更新と設定画面遷移のコードを書きます。
初回起動時にはデータはないのであるときとの条件分岐を書きます。
下記は一部。全体のコードは今回のコードの項をごらんください。

func load() {
        
        // インスタンス生成
        let defaults = NSUserDefaults.standardUserDefaults()
        
        // すでに設定でテキストフィールドに入力されている場合
        if defaults.objectForKey("TextField_Status") != nil {
            
            // キーに登録されている文字列を抽出,表示
            var value_string = defaults.objectForKey("TextField_Status") as? String
            self.stringLabel.text = value_string
        } else {
            self.stringLabel.text = "NO DATA" // 初回起動 or 未設定
        }
        
        // UISwitch の値(初回起動など区別)
        // 初回起動時
        if defaults.objectForKey("Switch_Status") == nil {
            self.boolLabel.text = "NO DATA" // 初回起動 or 未設定
        } else {
            // キーに保存されているBOOL値を抽出,表示
            var value_switch = defaults.boolForKey("Switch_Status")
            if value_switch  {
                self.boolLabel.text = "YES"
            } else {
                self.boolLabel.text = "NO"
            }
        }
    }

また,遷移先から戻ってきたときに値を更新するために,viewWillAppear に再度呼ぶように書いておく。

// 設定画面から戻ったときに load 関数を呼ぶ
override func viewWillAppear(animated: Bool) {
        
   // load関数で表示
   self.load()
}

あとは,SettingsViewCotroller へ遷移するコードを書けばいいです。

// Settings ボタンが押されたとき modal_segue1 の遷移
@IBAction func settingsAction(sender: AnyObject) {
        
    performSegueWithIdentifier("modal_segue1", sender: nil)
}


続いて,SettingsViewController.swift のコードですが,
同じく初回起動時にはデータはないのであるときとの条件分岐を書きます。
ただコードだけで書く場合は必要だと思いますが,Storyboard を用いた実装だと,
紐付けする際に Editing Did End とか Value Changed とか設定するので,
実質はコーディングする必要はないのかなと思いました。

  
// 値が変化(ユーザが変更)したら呼ばれる
        // Storyboardとヒモ付けする際指定してるのでいらないっぽい
        // テキストフィールド Ver
        textField.addTarget(self, action: "textFieldAction:", forControlEvents: UIControlEvents.EditingDidEnd)
        self.view.addSubview(textField)
        
        // UISwitch Ver
        switchBtn.addTarget(self, action: "switchAction:", forControlEvents: UIControlEvents.ValueChanged)
        self.view.addSubview(switchBtn)

それぞれの値をキーに保存する処理を書きます。

@IBAction func textFieldAction(sender: AnyObject) { // インスタンス生成 let defaults = NSUserDefaults.standardUserDefaults() // TextFiled_Status というキーに入力された文字列を保存 defaults.setObject(textField.text, forKey: "TextField_Status") // 値をすぐに更新 defaults.synchronize() } @IBAction func switchAction(sender: AnyObject) { // インスタンス生成 let defaults = NSUserDefaults.standardUserDefaults() // スイッチがオンかオフか if switchBtn.on { // Switch_Status というキーにスイッチの状態を保存する defaults.setBool(true, forKey: "Switch_Status") } else { // Switch_Status というキーにスイッチの状態を保存する defaults.setBool(false, forKey: "Switch_Status") } // 値をすぐに更新する defaults.synchronize() }

あとは元の画面に戻る処理などを書いて終わりです。
動作させてみると下記のようになります。
http://youtu.be/pjxix-VfvZU


今回のコード

今回のサンプルコード:https://github.com/MilanistaDev/SwiftModalNSUserDefaultsTest-

ViewController.swift
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var stringLabel: UILabel!
    @IBOutlet weak var boolLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // load関数で表示
        self.load()
    }
    
    // 設定画面から戻ったときに load 関数を呼ぶ
    override func viewWillAppear(animated: Bool) {
        
        // load関数で表示
        self.load()
    }
    
    func load() {
        
        // インスタンス生成
        let defaults = NSUserDefaults.standardUserDefaults()
        
        // すでに設定でテキストフィールドに入力されている場合
        if defaults.objectForKey("TextField_Status") != nil {
            
            // キーに登録されている文字列を抽出,表示
            var value_string = defaults.objectForKey("TextField_Status") as? String
            self.stringLabel.text = value_string
        } else {
            self.stringLabel.text = "NO DATA" // 初回起動 or 未設定
        }
        
        // UISwitch の値(初回起動など区別)
        // 初回起動時
        if defaults.objectForKey("Switch_Status") == nil {
            self.boolLabel.text = "NO DATA" // 初回起動 or 未設定
        } else {
            // キーに保存されているBOOL値を抽出,表示
            var value_switch = defaults.boolForKey("Switch_Status")
            if value_switch  {
                self.boolLabel.text = "YES"
            } else {
                self.boolLabel.text = "NO"
            }
        }
    }
    
    // Settings ボタンが押されたとき modal_segue1 の遷移
    @IBAction func settingsAction(sender: AnyObject) {
        
        performSegueWithIdentifier("modal_segue1", sender: nil)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

SettingsViewController.swift
import UIKit

// UITextFieldDelegate を追加
class SettingsViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var switchBtn: UISwitch!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // デリゲートを設定
        self.textField.delegate = self;
        
        self.main_method()
    }

    // メインメソッド
    func main_method() {
        
        // インスタンス生成
        let defaults = NSUserDefaults.standardUserDefaults()
        
        // すでに設定でテキストフィールドに入力されている場合
        if defaults.objectForKey("TextField_Status") != nil {
            
            // キーに登録されている文字列を抽出,表示
            var value_string = defaults.objectForKey("TextField_Status") as? String
            self.textField.text = value_string
        }
        
        // UISwitch の値(初回起動など区別)
        // 初回起動時
        if defaults.objectForKey("Switch_Status") == nil {
            self.switchBtn.on = false // 初回起動 or 未設定
        } else {
            // キーに保存されているBOOL値を抽出,表示
            var value_switch = defaults.boolForKey("Switch_Status")
            if value_switch  {
                self.switchBtn.on = true
            } else {
                self.switchBtn.on = false
            }
        }
        
        // 値が変化(ユーザが変更)したら呼ばれる
        // Storyboardとヒモ付けする際指定してるのでいらないっぽい
        // テキストフィールド Ver
        textField.addTarget(self, action: "textFieldAction:", forControlEvents: UIControlEvents.EditingDidEnd)
        self.view.addSubview(textField)
        
        // UISwitch Ver
        switchBtn.addTarget(self, action: "switchAction:", forControlEvents: UIControlEvents.ValueChanged)
        self.view.addSubview(switchBtn)
    }
    
    @IBAction func textFieldAction(sender: AnyObject) {
        
        // インスタンス生成
        let defaults = NSUserDefaults.standardUserDefaults()
        
        // TextFiled_Status というキーに入力された文字列を保存
        defaults.setObject(textField.text, forKey: "TextField_Status")
        
        // 値をすぐに更新
        defaults.synchronize()
    }
    
    @IBAction func switchAction(sender: AnyObject) {
        
        // インスタンス生成
        let defaults = NSUserDefaults.standardUserDefaults()
        
        // スイッチがオンかオフか
        if switchBtn.on {
            // Switch_Status というキーにスイッチの状態を保存する
            defaults.setBool(true, forKey: "Switch_Status")
        } else {
            // Switch_Status というキーにスイッチの状態を保存する
            defaults.setBool(false, forKey: "Switch_Status")
        }
        // 値をすぐに更新する
        defaults.synchronize()
    }
    
    // Back ボタンを押したときに元の画面に遷移
    @IBAction func backAction(sender: AnyObject) {
        
        self.dismissViewControllerAnimated(true, completion:nil)
    }
    
    // キーボードを閉じる
    func textFieldShouldReturn(textField: UITextField!) -> Bool {
        self.view.endEditing(true);
        return false;
    }

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

Swift で実装した感想

基本的に Objective-C と同じような感じだったのですぐに実装できました。
いわゆる暗黙の変数の型のため UserDefault の書き方が少し違っていたので
まとめてから本実装に移りました。まとめたものは次の記事で出します。
あと Bool 値が YES,NO ではなく true,false なのも少し混乱させました。
慣れれば全然問題なくなりそうですが。

おわりに

主に設定部分の実装などを想定した NSUserDefaults を用いた値保持の
基礎的なサンプルアプリを Swift で実装しました。
これくらいまできたら Swift の方が楽で短くコードが書ける気がしました。
細かいところでいろいろ調べることがありましたが楽しかったです。
次回は,Node.js を用いた通信系のコード書いてみようかなと考えています。
ご覧いただきありがとうございました。ここはこうしたほうがいいなどの
ご意見もいただけると勉強になります。おねがいします。

Twitterボタン
Twitter:@milanista_2nd
Apple 関係のこと,ガジェット系,ブログ更新などいろいろつぶやいています。
よろしければフォローお願いします!

初めてのアプリ作りました。無料なのでよろしければ是非。
 
FLAT Weather Clock

カテゴリ: ユーティリティ, 天気
価格:無料

Category: Utilities, Weather
Price: Free



 サポートページ日本語版:リンク
 Support Website(English):LINK

2014.12.23 Milanista



TAG index

0 件のコメント:

コメントを投稿