How to filter UICollectionView and keep keyboard up?

前端 未结 11 1549
旧时难觅i
旧时难觅i 2020-12-30 23:47

I\'ve added a UISearchBar to a UICollectionView and in the delegate searchBar:textDidChange: filter my model and call [collectio

相关标签:
11条回答
  • 2020-12-31 00:43

    I've just created a small test application. The following code does not hide the keyboard on entering characters in the searchbar. That said, [UITableView reloadData] does not resign the responder.

    - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
        return arc4random() % 10;
    }
    
    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {    
        UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath];
        return cell;
    }
    
    - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
        [self.collectionView reloadData];
    }
    

    Are you sure, you're not resigning it somewhere?

    0 讨论(0)
  • 2020-12-31 00:47

    The answer is to not reload the section which has the text field. I solved this problem by placing all items into a single search so it was possible to reload that single section.

    The existing screen that I was modifying was showing the index on the right with the letters to navigate to each section which means there were many section which makes it harder to know how to reload each of those sections without messing up internal state. To make it work when the text field becomes the first responder the organization of the collection view changes to place all items into a single section which is reloaded when the search is run. Now the top section is not reloaded so it does not lose focus.

    This way no undefined behavior is necessary like the other answers listed for this question.

    https://github.com/brennanMKE/PullDownSearch

    0 讨论(0)
  • 2020-12-31 00:48

    Here's how I managed it. I had my UISearchBar as the header supplementary view in my collection view. On text didchange for the searchbar delegate I set a flag that the search is active (or not) and reloaded the collectionview

    - (void)searchBar:(UISearchBar *)_searchBar textDidChange:(NSString *)searchText
    {
        if([searchText isEqualToString:@""])
        {
            activeSearch = FALSE;
        }
        else
        {
            activeSearch = TRUE;
        }
        [self filterContentForSearchText:searchText scope:nil];
        [self.collectionView reloadData];
    }
    

    Then in the cellForItemAtIndexPath I check if the keyboard is first responder and search is active, if not, I make it first responder:

     - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        ...
    
        if(activeSearch && ![searchBar isFirstResponder])
        {
            [searchBar becomeFirstResponder];
        }
    }
    
    0 讨论(0)
  • 2020-12-31 00:48

    I just added

        [searchBar becomeFirstResponder];
    

    after calling

        [collectionView reloadData];
    
    0 讨论(0)
  • 2020-12-31 00:52

    I faced this issue when dealing with UITextFields inside an UICollectionViewCell. I think search bar may follow the same path.

    I have a bunch of collection view cells which populate from;

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
        let question = questions[indexPath.row]
        let cell: QuestionBaseCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: cellName, for: indexPath) as! QuestionBaseCollectionViewCell
        cell.arrangeCell(question: question) // Here cell populates from server data 
        cell.delegate = self
        return cell
    }
    

    This QuestionBaseCollectionViewCell has a delegate method, which updates the answer of the question to its delegate. I need to update the server side data.

    In the delegate method; If I put reloadData method the textfield resigns and keyboard is disappearing.

    Also I do not have direct access to the UITextField which yields to I cannot use cell.textField.becomeFirstResponder() etc.

    So, I comment out the reloadData() method.

    func questionCollectionViewCell(_ cell: QuestionBaseCollectionViewCell, didChange choice: Choice) {
        guard let indexPath = collectionView.indexPath(for: cell) else { return }
        var question = questions[indexPath.row]
        guard let choiceIndex = question.choices?.firstIndex(where: { $0.id == choice.id }) else { return }
        question.choices?[choiceIndex] = choice
        questions[indexPath.row] = question
    
        // collectionView.reloadData()
    }
    

    Here is what I did;
    I made call to reloadData() after keyboard dismiss. See below.

    Just add a keyboardDidHideNotification to the corresponding view controller in viewWillAppear method (note: you may put wherever you want depends on your needs) as follows:

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(handleKeyboardDidHide(_ :)),
                                               name: UIResponder.keyboardDidHideNotification,
                                               object: nil)
    }
    

    and the observer method;

    @objc func handleKeyboardDidHide(_ notification: Notification) {
        collectionView.reloadData()
    }
    

    That's it. After the keyboard will hide, you may save your data.

    Hope it helps!

    0 讨论(0)
提交回复
热议问题