0

私は iOS 開発に不慣れで、Swift を使用して 2 番目のアプリを使用しています。テーブル ビュー コントローラーに SearchBar & Display 検索を組み込むことができません。

私のアプリには2つのビューがあります。最初のビューは果物の配列を生成します。最初のビューの出力: [リンゴ、オレンジ、バナナ、ナシ]。それから【ざくろ、梨、すいか、マスクメロン】など。一度に 1 つの配列。

果物の各配列は、NSFetchedResultsController を使用してコアデータに保存され、tableviewcontroller に表示されます。私の Coredata レイアウト:

import UIKit
import CoreData

@objc(Fruits)

class Fruits: NSManagedObject {
    @NSManaged var date: String
    @NSManaged var fruit: String
}

My Second View は果物のリストを表示します。これで、テーブル ビューの上部に検索バーとディスプレイを追加しました。しかし、私はそれを機能させることができません。

使用されるプロトコル:

class HistoryTableViewController: UITableViewController, NSFetchedResultsControllerDelegate{

宣言された変数:

let managedObjectContext: NSManagedObjectContext? = (UIApplication.sharedApplication().delegate as? AppDelegate)?.managedObjectContext
var fetchedResultsController: NSFetchedResultsController?
var fetchRequest = NSFetchRequest(entityName: "Fruits")

私のクラスには 2 つのコンセントがあります。

@IBOutlet weak var searchBar: UISearchBar! // the Search Bar & Display
@IBOutlet var tblHistory: UITableView! = nil // Table View

テーブル ビューのデータ入力:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return fetchedResultsController?.sections?.count ?? 0
    }
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {   
        return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
    }

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: (NSIndexPath!)) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
            if let cellFruit = fetchedResultsController?.objectAtIndexPath(indexPath) as? Fruits
            {
                cell.textLabel?.text = cellFruit.fruit
                cell.detailTextLabel?.text = cellFruit.date
            }
            return cell
    }

    // Override to support conditional editing of the table view.
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }

    //MARK: NSFetchedResultsController Delegate Functions
func controller(controller: NSFetchedResultsController, didChangeSection sectionInfo: NSFetchedResultsSectionInfo, atIndex sectionIndex: Int, forChangeType type: NSFetchedResultsChangeType) {

        switch type {
        case NSFetchedResultsChangeType.Insert:
            tableView.insertSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Delete:
            tableView.deleteSections(NSIndexSet(index: sectionIndex), withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Move:
            break
        case NSFetchedResultsChangeType.Update:
            break
        default:
            break
        }
    }

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
            //Delete object from entity, remove from list
            if editingStyle == .Delete {
            }
            switch editingStyle {
            case .Delete:
managedObjectContext?.deleteObject(fetchedResultsController?.objectAtIndexPath(indexPath) as! Fruits)
                do {
                    try managedObjectContext?.save()
                }catch{}
                print("Fruit set deleted successfully.")
            case .Insert:
                break
            case .None:
                break
            }
        }
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {

        switch type {
        case NSFetchedResultsChangeType.Insert:
            tableView.insertRowsAtIndexPaths(NSArray(object: newIndexPath!) as! [NSIndexPath], withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Delete:
            tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!) as! [NSIndexPath], withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Move:
            tableView.deleteRowsAtIndexPaths(NSArray(object: indexPath!) as! [NSIndexPath], withRowAnimation: UITableViewRowAnimation.Fade)
            tableView.insertRowsAtIndexPaths(NSArray(object: newIndexPath!) as! [NSIndexPath], withRowAnimation: UITableViewRowAnimation.Fade)
            break
        case NSFetchedResultsChangeType.Update:
            tableView.cellForRowAtIndexPath(indexPath!)
            break
        default:
            break
        }
    }

    func controllerWillChangeContent(controller: NSFetchedResultsController) {
        tableView.beginUpdates()
    }

    func controllerDidChangeContent(controller: NSFetchedResultsController) {
        tableView.endUpdates()
    }

コアデータから果物を検索し、ビューでフィルターするにはどうすればよいですか? Swift コーディングの検索バーと表示機能には、どのデリゲート関数を使用する必要がありますか?

ここのどこかで見逃したかもしれない概念についての助けをいただければ幸いです! ありがとう。

更新: Daniel Eggert が提案したように、検索コントローラー機能に述語を使用しようとしていますが、述語は常にnilを返します。私は何が欠けていますか???

クラスで宣言された変数:

var results: NSArray = []
var searchPredicate: NSPredicate?
var searchController: UISearchController!

述語関数:

//Search Functionality
        func updateSearchResultsForSearchController(searchController: UISearchController)
        {
            let searchText = self.searchController?.searchBar.text
            if let searchText = searchText {
                searchPredicate = NSPredicate(format: "fruit contains[cd] %@", searchText)
                results = (self.fetchedResultsController!.fetchedObjects?.filter() {
                    return self.searchPredicate!.evaluateWithObject($0)
                    } as! [Fruits]?)!
            self.tableView.reloadData()
            }
        }

    // Called when text changes (including clear)
    func searchBar(searchBar: UISearchBar, textDidChange searchText: String)
    {
        if !searchText.isEmpty
        {
            var predicate: NSPredicate = NSPredicate()
            predicate = NSPredicate(format: "fruit contains [cd] %@", searchText)
            let sortDescriptor = NSSortDescriptor(key: "date", ascending: true)
            fetchRequest.sortDescriptors = [sortDescriptor]
            fetchedResultsController?.fetchRequest.predicate? = predicate
            print(fetchedResultsController?.fetchRequest.predicate) // this is always nil. Why????????????
            do {
                try fetchedResultsController?.performFetch()
            }catch{}
            print("results array: \(results)") // this array should have values of the table view, but is empty. Why ?????????????????
            fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext!,
                sectionNameKeyPath: "fruit", cacheName: nil)
            fetchedResultsController?.delegate = self
            tableView.reloadData() 
        }
    }
4

2 に答える 2

0

検索可能なtableViewを実装したい場合は? UISearchResultsUpdatingというプロトコル メソッドの代わりに、UISearchBarDelegateプロトコル メソッドを使用する必要がありますsearchBar:textDidChange。プロトコルメソッドが利用できない場合はsearchBar:textDidChange、メソッドを使用できます! UISearchResultsUpdatingどちらのクラスも便利で強力です。そして実装が簡単

于 2016-02-19T01:52:44.143 に答える
0

取得した結果コントローラーに述語を設定したいとします。

フェッチされた結果コントローラーでフェッチ要求を変更したら、呼び出しperformFetch()てデータを再フェッチする必要があります。reloadData()次に、テーブル ビューを呼び出します。

ただし、重要な例のテキスト検索は、言語、ロケール、および Unicode がどのように相互作用するかにより、正しく行うのが難しい場合があります。私の本のテキストの章をお勧めします: https://www.objc.io/books/core-data/

于 2016-01-26T22:38:01.287 に答える