Проанализировать iOS SDK: запрос с использованием UISearchDisplayController

#ios #objective-c #uitableview #parse-platform

#iOS #objective-c #uitableview #анализ-платформа

Вопрос:

Сценарий = У меня есть приложение, которое позволяет пользователям искать других пользователей, которые используют службу. На странице поиска есть UISearchDisplayController, который, когда пользователь начинает вводить текст в строке поиска, программно отображает TableView (как и любой другой UISearchDisplayController) и фильтрует всех пользователей в базе данных в зависимости от того, что вводится (‘начинается с’). Таким образом, пользователь начнет вводить «B … r ….», и пользователи начнут заполнять TableView от «Brad» до «Brandon» и так далее на основе вводимого текста.

Вопрос = Как можно было бы спроектировать запрос parse для достижения этого эффекта?

Конкретные вопросы =

1) Когда и где начинать первоначальный запрос?…

 PFQuery *searchQuery = [PFUser query];
[searchQuery whereKey:@"username" containsString:controller.searchBar.text];
[searchQuery orderByDescending:@"updatedAt"];
[searchQuery findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {

    NSLog(@"%@", objects);

    searchArray = objects;

}];
  

в «searchDisplayControllerDidBeginSearch»?

2) Когда и куда мне поместить логику для заполнения TableView?

 PFObject *searchObject = [searchArray objectAtIndexPath:indexPath.row];
cell.nameLabel.text = searchObject[@"name"];
  

в «cellForRowAtIndexPath»?

Если есть кто-нибудь, кто знает это и может мне помочь, я был бы признателен.

Ответ №1:

Вот простой пример:

 #import <Parse/Parse.h>

@interface MySearchController : PFQueryTableViewController

@end
  

И реализация

 #import "MySearchController.h"

@interface MySearchController() <UISearchBarDelegate, UISearchDisplayDelegate>

@property (strong, nonatomic) IBOutlet UISearchBar *searchBar;
@property (nonatomic, strong) NSMutableArray *searchResults;

@end

@implementation MySearchController

- (id)initWithCoder:(NSCoder *)aCoder
{
    self = [super initWithCoder:aCoder];
    if (self) {
        // get users
        self.parseClassName = [PFUser parseClassName];
        self.pullToRefreshEnabled = YES;
        self.paginationEnabled = YES;
        self.objectsPerPage = 10;

        self.searchResults = [NSMutableArray new];
    }
    return self;
}

- (void)filterResults:(NSString *)searchTerm {

    [self.searchResults removeAllObjects];

    for (PFUser *user in self.objects)
    {
        NSString *username = user.username;
        if ([[username lowercaseString] hasPrefix:[searchTerm lowercaseString]])
        {
            [self.searchResults addObject:user];
        }
    }
}

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:  (NSString *)searchString {
    [self filterResults:searchString];
    return YES;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return (tableView == self.tableView) ? self.objects.count :  self.searchResults.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    PFUser *user = (tableView == self.tableView) ? self.objects[indexPath.row] : self.searchResults[indexPath.row];

    static NSString *identifier = @"reuseIdentifier";
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:identifier];
    }

    cell.textLabel.text = user.username;

    return cell;
}


@end
  

Главное, что меня сбило с толку, это то, что у вас есть два табличных представления, поэтому вы должны быть осторожны.
Одно из табличных представлений взято из исходного запроса, оно выдаст вам всех пользователей, это self.tableView . Другой — из результатов поиска, self.searchDisplayController.searchResultsTableView . Последний активен во время поиска. Следовательно, вы должны возвращать разные значения для каждого обычного метода tableviewcontroller. Количество строк равно либо self.objects.count , либо self.searchResults.count . Правильный пользователь — либо self.objects[indexPath.row] , либо self.searchResults[indexPath.row] . Легко проверить, с каким табличным представлением вы имеете дело в данном методе протокола, просто используйте это условие:
(tableView == self.tableView)

Комментарии:

1. Большое спасибо за ваш ответ, доктор! Однако, пожалуйста, обратите внимание, что в моем случае это просто обычный контроллер просмотра с панелью поиска UISearchDisplayController на нем. Не PFQueryViewController, как в вашем примере (хотя я делаю запрос на анализ данных). Ваш пример все еще применим к моему случаю? И если да, то происходит ли просто то, что TableView UISearchDisplayController просто «использует» методы выборки PFQueryViewController для заполнения самого себя?

2. @TomTesticool Отличное название, кстати, загляните PFQueryTableViewController , в него встроено много действительно крутых функций для разбора запросов: функция pull-to-refresh, на мой взгляд, самая крутая. И да, у него также есть метод -(PFQuery*)queryForTable , который он использует для извлечения объектов. Этот метод вызывается неявно и использует self.parseClassName поле для своего запроса простым return [query withParseClassName:self.parseClassName] способом. Я бы посоветовал вам использовать этот класс, но в uiviewcontroller все еще возможно. Попробуйте поместить мой класс в свою раскадровку и посмотрите, насколько это эффективно.

3. Спасибо, моя мать дала мне это… Мне тоже нравятся некоторые PFQueryViewControllers. Дело в том, что VC, который я использую, делает больше, чем просто табличное представление. Я получил коллекцию и другие вещи, которые тоже происходят. Так что я не уверен, будет ли это вариантом. Но если я слышу, что вы говорите, все, что мне нужно сделать, это подклассировать мой VC из PFQueryTableViewController и просто использовать его удобный для запросов метод для заполнения моего представления таблицы поиска, тогда я собираюсь попробовать это? Это правильно, или я наполовину отсталый?

4. @TomTesticool только наполовину. Лучшее, что вы можете сделать, это сохранить один VC со всеми остальными материалами, не относящимися к запросам. Затем поместите представление контейнера в этот vc и внедрите свой PFQueryTableViewController в это представление контейнера, щелкнув элемент управления на представлении контейнера и перетащив его в, TableViewController класс которого является вашим пользовательским классом запроса. В методе prepareToSegue вашего содержащего vc вы можете получить ссылку на таблицу запросов vc, segue.destinationViewController а затем вы можете использовать это, чтобы возиться с ней, или извлекать из нее данные для обновления контейнера vc.

5. Это хороший способ обойти. Я собираюсь попробовать кое-что из этого материала и посмотреть, к чему это меня приведет. Я знаю, что мне, вероятно, в любом случае, в какой-то момент придется добавить PFQTVC.