9240


`TableView`のデータを削除しようとすると、何のエラーも表示せずにアプリが動かなくなります。下記のコードのどこがおかしいでしょうか？個人的にオプショナルに関する部分が怪しいかと思っているのですが、具体的にわかりません。。。どなたか不具合の原因が分かる方がいれば教えていただきたいです。すみませんが、よろしくお願いします。

DataViewControllerクラス

[code]

    var nounData: NSMutableArray = NSMutableArray()
    let dbhelper = DatabaseHelper()
    nounData.addObjectsFromArray(dbhelper.outputWord("AAA"))    //データベースにあるString型の値が入る
    
    func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!){            
        if(editingStyle == UITableViewCellEditingStyle.Delete){
            removeData("AAA", wordData: nounData, indexPath: indexPath.row)
        }
    }
    
    func removeData(speech: String, wordData: NSMutableArray, indexPath: Int) {
        let dbhelper = DatabaseHelper()
        dbhelper.removeWord(speech, word: (wordData.objectAtIndex(indexPath) as? String)!)
        wordData.removeObjectAtIndex(indexPath)
        self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
    }
    
[/code]

DatabaseHelperクラス

[code]

    func removeWord(speech: String, word: Optional<String>) {
            let realm = RLMRealm.defaultRealm()
            realm.transactionWithBlock( { () -> Void in
            realm.deleteObjects(Word.objectsWhere("speech == %@ AND word == %@", speech, word!))
        })
    }
    
[/code]


CC BY-SA 3.0
2015-04-14T23:19:43.457
9168
2015-04-16T22:49:39.757
2015-04-15T22:34:34.817
5210
5210
question
ios swift uitableview optional
TableViewのデータを削除しようとするとアプリが動かなくなる


UITableViewからデータを削除する際には、  
データソースからの削除だけでなく行の削除自体も行う必要があります。

[code]

    removeData("AAA", wordData: nounData, indexPath: indexPath.row)
    
[/code]

の後に、

[code]

    tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
    
[/code]

が必要となります。


CC BY-SA 3.0
2015-04-15T01:49:37.660
9175
2015-04-15T01:49:37.660
3227
9168
answer


あなたの質問に対する、直接の回答ではありません。提示コードの中に、気になる点があったので、それに対するアドバイスをしたいと思います。

[code]

    var nounData: NSMutableArray = NSMutableArray()
    
[/code]

Swiftで、配列オブジェクトに、`NS(Mutable)Array`を使うのは、デメリットはあっても、メリットはないに等しいといえます。  
`NS(Mutable)Array`は、そのメンバーの型は`AnyObject`（Objective-
Cでいえば`id`型）になります。元のオブジェクトがどのような型であっても、メンバーに代入するとき、`AnyObject`に自動でアップキャストされます。しかし、メンバーからオブジェクトを取り出すとき、自動でダウンキャストはしてくれません。手動でダウンキャストしなければいけません。そして、Swiftは型に厳密な言語なので、ダウンキャストに失敗したときの対処をしたプログラムをしないと、コンパイルできません。  
「ダウンキャストに失敗したときの対処」とは、具体的には、`as?`を使ってキャストし、ダウンキャストできなかったとき、`nil`を渡すという処理をするのが一般的です。すなわちメンバーから取り出したオブジェクトは、オプショナル型をとります。なお、Swift
1.2より、`as!`というキャストが追加され、強制で非オプショナル型にすることができるようになりました。

[code]

    dbhelper.removeWord(speech, word: (wordData.objectAtIndex(indexPath) as? String)!)
    
[/code]

これはあなたの提示コードの中の1行ですが、`(wordData.objectAtIndex(indexPath) as?
String)!`は、`as!`を使って、`wordData.objectAtIndex(indexPath) as! String`と書き直せるはずです。  
Swiftでは、できる限りオプショナル型を使わずに、非オプショナル型の変数だけ使って、プログラムするというのが、ひとつのテクニックになります。配列オブジェクトは、SwiftのArray型を使い、メンバーの型を明示しておくことで、そのメンバーも、メンバから取り出すオブジェクトも、非オプショナル型として取り扱うことができます。

> var nounData: NSMutableArray = NSMutableArray()
[code]

    var nounData = [String]()
    
[/code]

> nounData.addObjectsFromArray(dbhelper.outputWord("AAA"))
[code]

    nounData.extend(dbhelper.outputWord("AAA"))
    
[/code]

※DatabaseHelperクラスが、配列に関してどういう実装をしているかによって、この記述は変わってきます。

> dbhelper.removeWord(speech, word: (wordData.objectAtIndex(indexPath) as?
> String)!)
[code]

    dbhelper.removeWord(speech, word: wordData[indexPath])
    
[/code]

ごらんのように、記述するコード量が、はっきり少なくなるメリットもあります。


CC BY-SA 3.0
2015-04-15T06:47:57.627
9190
2015-04-15T09:34:46.297
2015-04-15T09:34:46.297
7362
7362
9168
answer

[code]

    func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!){            
        if(editingStyle == UITableViewCellEditingStyle.Delete){
            removeData("AAA", wordData: nounData, indexPath: indexPath.row)
        }
    }
    
[/code]

上記のメソッドを

[code]

    func tableView(tableView: UITableView!, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath!){            
        if(editingStyle == UITableViewCellEditingStyle.Delete){
            removeData("AAA", wordData: nounData, indexPath: indexPath)
        }
    }
    
[/code]

に変更することでアプリが動かなくなることがなくなりました。  
変更箇所がわかりにくいのですが、`removeData`の第三引数を`indexPath.row`から`indexPath`に変更しました。`removeData`にある

[code]

    self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
    
[/code]

のメソッドの第一引数が`indexPath.row`ではなく`indexPath`を取るからでした。  
ご回答くださった皆様ありがとうございました。


CC BY-SA 3.0
2015-04-16T22:49:39.757
9240
2015-04-16T22:49:39.757
5210
9168
answer