#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.