QA@IT

Swiftで検索文字列にヒットしたNewsのみを表示する

9581 PV

いつも大変お世話になっております。Agaと申します。

Swiftを現在勉強中です。

ある参考書のサンプルプログラムを自分なりに改良
しています。(ニュースアプリ)

追加しようとしている機能は、検索文字列を入力し
更新をかけると、ヒットしたニュースのみを表示
させるというものです。

ですが、検索文字列がないニュースを削除できずにいます。
お手数おかけしますがご教授のほどよろしくお願い致します。

@IBOutlet weak var newsSearch: UISearchBar!
var entries: NSMutableArray = NSMutableArray()【2014/11/9 追加】

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        var cell : UITableViewCell

        if indexPath.row == 0 {
            cell = tableView.dequeueReusableCellWithIdentifier("top") as UITableViewCell
        }
        else{
            cell = tableView.dequeueReusableCellWithIdentifier("news") as UITableViewCell
        }

        var entry = entries[indexPath.row] as NSDictionary

        //検索文字が含まれるニュースのみを取り出す
        var searchStr : NSString = entry["title"] as NSString!
        var loc = searchStr.rangeOfString(newsSearch.text).location

        if loc == NSNotFound && newsSearch.text != "" {

            //検索文字がないニュースを削除する
            entries.removeObjectAtIndex(indexPath.row)

        } else if loc != NSNotFound && newsSearch.text != "" {

            var titleLabel = cell.viewWithTag(1) as UILabel
            titleLabel.text = entry["title"] as? String
            var descriptionLabel = cell.viewWithTag(2) as UILabel
            descriptionLabel.text = entry["contentSnippet"] as? String

            // NSDateFormatterを作って、日付を文字列に変換する
            var date = entry["date"] as NSDate
            var formatter = NSDateFormatter()
            formatter.locale = NSLocale(localeIdentifier: "ja-JP")
            formatter.dateStyle = NSDateFormatterStyle.LongStyle
            formatter.timeStyle = NSDateFormatterStyle.MediumStyle
            var dateStr = formatter.stringFromDate(date)

            var dateLabel = cell.viewWithTag(3) as UILabel
            dateLabel.text = dateStr

            var urlString = entry["url"] as String
            var index = find(newsUrlStrings, urlString)
            var imageName = imageNames[index!]
            var image = UIImage(named: imageName)

            var imageView = cell.viewWithTag(4) as UIImageView
            imageView.image = image

        } else {

            var titleLabel = cell.viewWithTag(1) as UILabel
            titleLabel.text = entry["title"] as? String
            var descriptionLabel = cell.viewWithTag(2) as UILabel
            descriptionLabel.text = entry["contentSnippet"] as? String

            // NSDateFormatterを作って、日付を文字列に変換する
            var date = entry["date"] as NSDate
            var formatter = NSDateFormatter()
            formatter.locale = NSLocale(localeIdentifier: "ja-JP")
            formatter.dateStyle = NSDateFormatterStyle.LongStyle
            formatter.timeStyle = NSDateFormatterStyle.MediumStyle
            var dateStr = formatter.stringFromDate(date)

            var dateLabel = cell.viewWithTag(3) as UILabel
            dateLabel.text = dateStr

            var urlString = entry["url"] as String
            var index = find(newsUrlStrings, urlString)
            var imageName = imageNames[index!]
            var image = UIImage(named: imageName)

            var imageView = cell.viewWithTag(4) as UIImageView
            imageView.image = image

        }

        return cell
    }

エラー内容
terminating with uncaught exception of type NSException

回答

ここにこのコードを書いてもダメです。

//検索文字がないニュースを削除する
entries.removeObjectAtIndex(indexPath.row)

この関数が呼ばれる前の段階で、entriesの値をフィルターしてください。

(追記)
フィルターの条件は以下のコードを参考にしてください。

//検索文字が含まれるニュースのみを取り出す
var searchStr : NSString = entry["title"] as NSString!
var loc = searchStr.rangeOfString(newsSearch.text).location

if loc == NSNotFound && newsSearch.text != "" {
  //検索文字がないニュースを削除する
  entries.removeObjectAtIndex(indexPath.row)
}
編集 履歴 (1)
  • この質問に回答するで返信してしまいました。
    stripe様
    ご回答いただきありがとうございます。
    フィルターの件ですが、下記のようなコードを
    追加するのだと思うのですが、
    entries[indexPath.row].filter({.....})
    お恥ずかしい限りですが、({.....})の中に入れる
    コードが思い浮かびません。申し訳ありませんが
    再度ご教授の程、お願いいたします
    -
  • stripe様
    いつも大変お世話になっております。
    filterメソッドについて試行錯誤しています。
    大変申し訳ありませんが、追記事項について
    ご教授の程よろしくお願い致します。
    -
  • stripe様
    途中経過を報告いたします。追記事項につきまして
    ご指摘事項等ありましたら、ご教授のほどよろしく
    お願いいたします。
    -
  • stripe様 filterは使用しませんでした。申し訳ありません。
    何とか求める機能は実装できたと思います。色々
    アドヴァイスありがとうございました。
    -

stripe様

ご回答いただきありがとうございます。
フィルターの件ですが、下記のようなコードを
追加するのだと思うのですが、
entries[indexPath.row].filter({.....})
お恥ずかしい限りですが、({.....})の中に入れる
コードが思い浮かびません。お手数おかけし申し訳ありませんが
再度ご教授の程、よろしくお願いいたします。

参考先サイトでの情報

var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

numbers.filter({ $0 % 2 == 0 })

//=> [2, 4, 6, 8, 10]

【2014/11/7 追記事項】

コード

var entry = entries[indexPath.row] as NSDictionary        
var searchStr : NSString = entry["title"] as NSString!
var loc = searchStr.rangeOfString(newsSearch.text).location
entries[indexPath.row].filter({loc != NSNotFound})←この部分

エラー内容

'AnyObject' does not have a member named 'filter'

上記エラー内容が発生しております。entries.filterメソッドとした場合は
メソッド自体が表示されません。Array()のみのメソッドなのでしょうか?

【2014/11/11 追加事項】

コード

var entry = entries[indexPath.row] as NSMutableDictionary

var valArray : [NSMutableArray] = Array()
valArray.append(self.entries[indexPath.row] as NSMutableArray)

valArray.filter({() -> Bool in <----引数が出てこず困っています

var searchStr : NSString = entry["title"] as NSString!
var loc : Int = searchStr.rangeOfString(self.newsSearch.text).location

if  loc == NSNotFound && self.newsSearch.text != "" {

        self.entries.removeObjectAtIndex(indexPath.row)            
        return true

    }else{
})

途中報告となります。ご指摘事項等ありましたら、よろしくお願い致します。

【2014/11/19 最終】

filter は使用しておりませんが、何とか検索でヒットしたニュースのみ
表示することはできました。(tableViewの表示方法については不十分の
結果ですが・・・)stripe様ありがとうございました。

コード

for var i = 0 ; i < entries.count ; i++ {
   var entry = entries[i] as NSMutableDictionary

      //ヒットしないニュースを削除する
      var searchStr : NSString = entry["title"] as NSString!

      loc = searchStr.rangeOfString(self.newsSearch.text).location

      if (loc == NSNotFound) {
          for (rmvId, rmvVal) in entry {
              entry.removeObjectForKey(rmvId)
          }
      }
      else{
          self.entries.addObjectsFromArray(entries)
      }
}
編集 履歴 (3)
  • filter関数は配列(Array)に対して使います。また引数のクロージャは1つの引数を取ります。 -
  • 引数が出てこない??自分で引数を書けばいいのでは? -
ウォッチ

この質問への回答やコメントをメールでお知らせします。