9106


最初に表示される`ViewController`の`TextField`に値を入れてそれをデータベースに入れ、次にデータベースの値を`TableView`に一覧表示する`ViewController`を表示した時に、先ほど入れた値がTableViewに表示されません。一度アプリを終了してもう一度立ち上げて`TableView`の`ViewController`を表示すると値は表示されています。しかし値を入れてからすぐに反映させたいです。次のやり方を試したのですが、ダメでした。

<https://stackoverflow.com/questions/25921623/how-to-reload-tableview-from-
another-view-controller-in-swift>

ちなみに`TabBarController`を使っています。  
どうすればすぐにデータベースに入れた値を`TableView`に反映させることができるでしょうか？  
どなたか分かる方がいれば教えていただきたいです。すみませんが、よろしくお願いします。

最初のViewController

[code]

    @IBAction func registerWord(sender: AnyObject) {
            if self.textField.text == "" {
    
            } else {
    
                let dbhelper = DatabaseHelper()
                dbhelper.inputWordToDatabase(self.registerWordStore, registerSpeech: self.registerSpeechStore)
    
                self.textField.text = ""
    
                showCompleteAlert()
            }
        }
    
[/code]

データベースを処理するクラス

[code]

    func inputWordToDatabase(registerWord: String, registerSpeech: String) {
            let ud = NSUserDefaults.standardUserDefaults()
            autoincrementId = ud.integerForKey("incrementKey")
    
            let word = Word()
            word.id = autoincrementId
            word.speech = registerSpeech
            word.word = registerWord
    
            let realm = RLMRealm.defaultRealm()
            realm.transactionWithBlock({ () -> Void in
                realm.addObject(word)
            })
    
            autoincrementId++
    
            ud.setInteger(autoincrementId, forKey: "incrementKey")
        }
    
        func outputWord(speech: String) -> Array<String> {
            var wordData: [String] = []
            let wordArray = Word.objectsWhere("speech CONTAINS %@", speech)
    
            for item in wordArray {
                if let wordStore = item as? Word {
                    wordData.append(wordStore.word)
                }
            }
    
            return wordData
        }
    
[/code]

TableViewのViewController

[code]

    override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
    
            self.segmentedControl.addTarget(self, action: "changeData:", forControlEvents: .ValueChanged)
    
            let dbhelper = DatabaseHelper()
            nounData = dbhelper.outputWord("名詞")
            verbData = dbhelper.outputWord("動詞")
            adjectiveData = dbhelper.outputWord("形容詞")
            newWordData = dbhelper.outputWord("オリジナル")
        }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "Cell")
            cell.backgroundColor = UIColor.clearColor()
    
            switch segmentedControl.selectedSegmentIndex {
                case 0:
                    cell.textLabel?.text = nounData[indexPath.row]
                case 1:
                    cell.textLabel?.text = verbData[indexPath.row]
                case 2:
                    cell.textLabel?.text = adjectiveData[indexPath.row]
                default:
                    cell.textLabel?.text = newWordData[indexPath.row]
                }
    
            return cell
        }
    
[/code]


CC BY-SA 3.0
2015-04-12T23:36:57.280
9086
2015-04-13T10:45:49.323
2017-05-23T12:38:56.083
-1
5210
question
swift uitableview
TableViewがすぐ更新されない


`Notification`の基礎について説明します。  
Objective-C、Swiftは、いうまでもなくオブジェクト指向言語ですが、オブジェクト指向では、オブジェクト間の連携、外部からオブジェクトをどう制御するかが問題となります。Objective-C、Swiftでは、いくつかのしくみがそのために用意されています。Action-
TargetやResponder
Chain、Delegateなどがそうですが、それらとは異なった性質のNotificationが用意されています。Notification以外は、基本1対1の連携ですが、Notificationでは、ひとつのオブジェクトから発せられた「通知」を、複数のオブジェクトに送ることができるという特長を持ちます。（もちろん1対1の連携にも使えます）  
アプリケーションは、ひとつの`NotificationCenter`というオブジェクトを持ちます。あるオブジェクトが、「通知」を発信すると、NotificationCenterがその通知を受け取り、複数のオブジェクトに向けて、その通知を発信するという仕事をします。  
NotificationCenterは、`NSNotificationCenter.defaultCenter()`で参照できます。  
NotificationCenterに通知を伝えることを、`Post`といいます。

[code]

    let notificationCenter = NSNotificationCenter.defaultCenter()
    notificationCenter.postNotificationName("MyNotification", object: self, userInfo: ["Item1": "Sunday"])
    
[/code]

メソッド`postNotificaionName()`の第1引数は、通知の名称で、String型です。第2引数は、通知を送るオブジェクトです。通常`self`で、`nil`でもかまいません。第3引数は、通知といっしょに送る情報で、Dictionary型とします。情報がなければ、`nil`とします。このメソッドを使って、NotificationCenterに通知をPostします。

次は通知を受け取るオブジェクトの話をします。  
NotificationCenterから発信する通知は、不特定多数のオブジェクトに送られるのではなく、NotificationCenterに登録したオブジェクト（`Observer`）だけに送られます。NotificationCenterの通知を受け取るには、まず`addObserver()`というメソッドを使って、NotificationCenterに登録する必要があります。

[code]

    let notificationCenter = NSNotificationCenter.defaultCenter()
    notificationCenter.addObserver(self, selector: "didReceiveNotification:", name: "MyNotification", object: nil)
    
[/code]

`addObserver()`の第1引数は、オブザーバになるオブジェクトで、多くのケースで`self`です。第2引数は、通知を受け取ったときに実行するメソッドを、セレクタで指定します。第3引数は、通知の名称をString型で記述します。`postNotificationName()`の引数に対応します。第4引数は、通知を発信したオブジェクトを示しますが、`nil`にすると、NotificationCenterが発信した通知すべてを受け取るようになりますから、通常`nil`にします。

通知を受け取ると、セレクタで指定したメソッドが実行されます。

[code]

    func didReceiveNotification(notification: NSNotification) {
        if let newItem = notification.userInfo!["Item1"] as? String {
            println("Received String = \(newItem)")
        }
    }
    
[/code]

引数は`NSNotification`型です。引数のプロパティ`userInfo`で、`postNotificationName()`で渡した情報を得ることができます。なお、プロパティ`userInfo`も、`Dictionary`のメンバーも、Otional型であることに、注意してください。

以下サンプルコードです。Tabベースのアプリで、`FirstViewController`にテーブルがあります。`SecondViewController`に移ると、そこに`TextField`があって、そこに文字列を入力し、リターンキーを押すと、`FirstViewController`のテーブルに、行が追加されるというプログラムです。

**FirstViewController.swift**

[code]

    import UIKit
    
    class FirstViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
        @IBOutlet weak var tableView: UITableView!
        var dataArray = [String]()
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            dataArray.append("Sunday")
            dataArray.append("Monday")
            dataArray.append("Tuesday")
            // NotificationCenterに登録する。
            let notificationCenter = NSNotificationCenter.defaultCenter()
            notificationCenter.addObserver(self, selector: "didReceiveItem:", name: "AddItem", object: nil)
        }
        // 通知を受け取って実行するメソッド
        func didReceiveItem(sender: NSNotification) {
            if let newItem = sender.userInfo!["TextItem"] as? String {
                // テーブルのソースになる配列に、メンバーを追加。
                dataArray.append(newItem)
                // テーブルビューを再描画
                tableView.reloadData()
            }
        }
        // テーブルのDataSource
        func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return dataArray.count
        }
    
        func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
            cell.textLabel?.text = dataArray[indexPath.row]
    
            return cell
        }
    
    }
    
[/code]

**SecondViewVontroller.swift**

[code]

    import UIKit
    
    class SecondViewController: UIViewController, UITextFieldDelegate {
    
        @IBOutlet weak var textField: UITextField!
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        // テキストフィールドのDelegate
        func textFieldShouldReturn(textField: UITextField) -> Bool {
            // 通知を発信する。
            let notificationCenter = NSNotificationCenter.defaultCenter()
            notificationCenter.postNotificationName("AddItem", object: nil, userInfo: ["TextItem": textField.text])
            // キーボードを下げる。
            textField.resignFirstResponder()
            return true
        }
    
    }
    
[/code]

※サンプルコードは、Xcode 6.3 + Swift 1.2で記述したものです。旧バージョンでは、細部で異なる点があると思います。


CC BY-SA 3.0
2015-04-13T07:41:27.967
9106
2015-04-13T10:45:49.323
2015-04-13T10:45:49.323
7362
7362
9086
answer