2016-11-14 4 views
3

Ich möchte ein Wörterbuch der Übungen für den Namenschlüssel suchen und dann das gefilterte Ergebnis in der Tabellenansicht anzeigen. Ich benutze diese FunktionArray filtern und in der Tabellenansicht anzeigen?

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { 
    let filtered = exercises.filter { $0["name"] == searchText } 
    print(filtered) 

    if(filtered.count == 0){ 
     searchActive = false; 
    } else { 
     searchActive = true; 
    } 
    self.exercisesTableView.reloadData() 
} 

Variablen:

var exercises = [Exercise]() 
var filtered: [NSMutableArray] = [] 
var searchActive: Bool = false 

In der Suchfunktion ich den Fehler

Type'Exercise erhalten‘hat keine Index Mitglieder

und Dann habe ich das Problem, dass das Ergebnis ein NSMutableArray ist und daher kann ich das resul nicht setzen t Namen als Zelltext anzuzeigen

Wert kann nicht vom Typ 'NSMutableArray' konvertieren 'String' in Zwang zu geben

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 
    if (searchActive){ 
     cell.textLabel?.text = filtered[indexPath.row] as String 
    } else { 
     let exercise = exercises[indexPath.row] 

     cell.textLabel!.text = exercise.name 
    } 
    return cell 
} 

Hier ist meine Übung Wörterbuch als Referenz:

final public class Exercise { 
    var id: Int 
    var descrip: String 
    var name: String 
    var muscles: [Int] 
    var equipment: [Int] 

    public init?(dictionary: [String: Any]) { 

     guard 
      let id = dictionary["id"] as? Int, 
      let descrip = dictionary["description"] as? String, 
      let name = dictionary["name"] as? String, 
      let muscles = dictionary["muscles"] as? [Int], 
      let equipment = dictionary["equipment"] as? [Int] 

      else { return nil } 

     self.id = id 
     self.descrip = descrip 
     self.name = name 
     self.muscles = muscles 
     self.equipment = equipment 

    } 

Ich kann den zweiten Fehler beheben, indem ich var filtered: [String] = [] so kann es als eine Zelle Titel verwendet werden, aber das löst nicht den ersten Fehler und ich bin nicht sicher, ist der richtige Weg, um darüber zu gehen ?

Antwort

2

Ihre filtered auch Art von [Exercise] und Sie müssen filtern es mögen.

var filtered = [Exercise]() 

self.filtered = exercises.filter { $0.name == searchText } 

Hier $0 ist Art von Exercise Objekt, so müssen Sie seine Eigenschaftsnamen für den Zugriff auf $0.name verwenden.

Edit: Wenn Sie filtered als Art von [String] mit nur Namen wollen, dann können Sie sowohl map und filter wie diese verwenden müssen.

self.filtered = exercises.filter { $0.name == searchText }.map { $0.name } 

ODER

self.filtered = exercises.map { $0.name }.filter { $0 == searchText } 

oder direkt mit filterMap als @dfri vorgeschlagen.

self.filtered = exercises.flatMap{ $0.name == searchText ? $0.name : nil } 
+0

Vielen Dank für diese, aber wenn ich auch gefilterte Menge an = [Übung]() Wie soll ich gemeint Ordnen Sie es dem Zellennamen zu, wenn es kein String mehr ist? Siehe den Teil meines Codes cell.textLabel? .text = gefiltert [indexPath.row] als String – infernouk

+0

@infernouk Überprüfen Sie die bearbeitete Antwort :) –

+0

Ich habe es versucht und es mag es nicht, muss ich auch die Variable bearbeiten oder einfach den angegebenen Code eingeben? Fehler sind: Wert des Typs 'String' kann nicht in den Closure-Ergebnistyp 'Übung' und in die Tabellenzellen-Namensanweisung konvertiert werden: Wert des Typs 'Übung' kann nicht in den Datentyp 'String' konvertiert werden – infernouk

0

Das Problem hier ist $0["name"] == searchText. $0 in diesem Zusammenhang ist von Excersise Typ und Sie beziehen sich darauf, wie es ein Array ist. Diese Zeile sollte wie folgt aussehen:

let filtered = exercises.filter { $0.name == searchText }

3

Ich sagte Ihnen gestern vergessen, die Wörterbuch Semantik wenn eine benutzerdefinierte Klasse.
Verwenden Sie keine Key-Subskriptionen!

Wie in den anderen Antworten erwähnt haben Sie filtered auch als [Exercise]

var filtered = [Exercise]() 

zu erklären und filtern

self.filtered = exercises.filter { $0.name == searchText } 

Allerdings, wenn Sie auch suchen mögen für Teilstrings verwenden

self.filtered = exercises.filter {$0.name.range(of: searchText, options: [.anchored, .caseInsensitive, .diacriticInsensitive]) != nil } 

Aber

da beide gefilterten und ungefilterten Arrays vom Typ [Exercise] Sie cellForRowAtIndexPath diese Weise ändern müssen

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) 
    let exercise : Exercise 
    if (searchActive){ 
     exercise = filtered[indexPath.row] 
    } else { 
     exercise = exercises[indexPath.row] 
    } 
    cell.textLabel!.text = exercise.name 
    return cell 
} 
+0

danke ive probierte dies aus, da es sauberer erscheint, um den Filter vom gleichen Typ zu halten, keine Fehler, nur dass ich immer noch diesen seltsamen Absturz bei der Eingabe eines Briefes in die Suchleiste bekomme, wie in Niravs Antwortkommentar – infernouk

+0

erwähnt Verwenden Sie 'UISearchController'? Wenn ja, benutze 'searchResultController.isActive', um den Suchzustand und nicht eine benutzerdefinierte boolesche Variable zu überprüfen. – vadian

+0

also muss ich searchResultController als Variable deklarieren? Wenn Sie es nur für searchResultController.isActive austauschen, führt dies zu nicht aufgelösten Bezeichnerfehlern. Ich habe searchController = UISearchController (searchResultsController: nil) im Moment – infernouk

Verwandte Themen