0

I'm coding a viewController which permit to search specifics users. I have a searchBar and a listener:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
      doSearch()
}

func doSearch() {
      if let searchText = searchBar.text?.lowercased() {
         self.users.removeAll()
         self.tableView.reloadData()
         Api.User.queryUsers(withText: searchText, completion: { (user) in
               self.users.append(user)
               self.tableView.reloadData()
         })
      }
}

The queryUser func:

func queryUsers(withText text: String, completion: @escaping (Userm) -> Void) {
      REF_USERS.queryOrdered(byChild: "username_lowercase").queryStarting(atValue: text).queryEnding(atValue: text+"\u{f8ff}").queryLimited(toLast: 5).observeSingleEvent(of: .value) { (snapshot) in
         snapshot.children.forEach({ (s) in
            let child = s as! DataSnapshot
            if let dict = child.value as? [String: Any] {
               let user = Userm.transformUser(dict: dict, key: child.key)
               completion(user)
            }
         })
      }
}

The problem is that, with Firebase, when I write too fast I can have the same user displayed several times. I would like to have a function which can do something like this:

// if user is not already contained in the array
-> Display it

I tried to use the .contains() function but I have not arrived at a good result, I'm still a beginner in Swift.

Do you have any idea please?

halfer
  • 19,824
  • 17
  • 99
  • 186
KevinB
  • 2,454
  • 3
  • 25
  • 49
  • I found a topic which respond to my problem : https://stackoverflow.com/questions/24330056/how-to-throttle-search-based-on-typing-speed-in-ios-uisearchbar I tried your answers but it didn't worked well. Thank you very much. – KevinB Dec 12 '17 at 15:18

2 Answers2

0

You can choose to filter the array the TableView uses to display data. This can be done either by casting it to a Set (since Sets only contain unique values) and then back to an Array again, or with an extension to the User class so it conforms to the Equatable protocol. Using the set option can be done like this:

let array = ["one", "one", "two", "two", "three", "three"]
let unique = Array(Set(array))
// ["one", "two", "three"]

Using the protocol would look something like this:

extension User: Equatable {
    static func == (lhs: User, rhs: User) -> Bool {
    //make sure the User class has something that can uniquely identify them.
        return lhs.identifier == rhs.identifier
    }
}
JillevdW
  • 1,087
  • 1
  • 10
  • 21
0

I think you can use filters to get a valid array.

something like this:

var someObject:SomeObject = receivedObjectFromMars
var arrayOfObjects:Array<SomeObject> = [object1, object2, object3, object4]
// imagine that 'someObject' has the same email of object1 and object 4.
var filteredArray:Array<String> = [];

filteredArray = arrayOfObjects.filter({ (obj) -> Bool in
    //so when you filter the array, you will compare a specific
    // attribute (e.g: email)
    return obj.email != someObject.email
})

// current filteredArray = [object2, object3]

So, after that, if you want to add the specific element, you just add.

filteredArray.append(someObject);

You can use it with other types, like strings, int, whatever.

get help here, too: Swift 3 filter array of objects with elements of array

JLU.