使用SearchBar时表格视图中的图像

时间:2016-11-06 00:20:04

标签: ios objective-c uitableview searchbar

我在Objective-C中使用Xcode开发应用程序。 该应用程序有一个TableView与一系列餐厅。我的问题是,当我尝试使用SearchBar时,我使用Title(餐厅的名称作为过滤器),但是当我在过滤器搜索后显示行时,只有标题是正确的。另一个标签和单元格中的图像是错误的(它显示正确的标题,但图像和另一个标签(描述标签)与原始tableview中的第一行相同)。

我必须更改我的cellForRowAtIndexPath方法,但我现在不知道如何更改它。

这是名为MainTableViewController.h的TableViewController

#import <UIKit/UIKit.h>

@interface MainTableViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate>

@property (weak, nonatomic) IBOutlet UIBarButtonItem *barButton;

//@property (nonatomic, strong) NSArray *Images;
//@property (nonatomic, strong) NSArray *Description;
//@property (nonatomic, strong) NSArray *Title;
@property (nonatomic, strong) NSMutableArray *Title;
@property (nonatomic, strong) NSMutableArray *Images;
@property (nonatomic, strong) NSMutableArray *Description;
@property (nonatomic, strong) NSMutableArray *filteredRest;
@property BOOL isFiltered;

@property (strong, nonatomic) IBOutlet UITableView *RestTableView;

@property (strong, nonatomic) IBOutlet UITableView *mySearchBar;

@end  

这是我的MainTableViewController.c

#import "MainTableViewController.h"
#import "SWRevealViewController.h"
#import "RestTableViewCell.h"
#import "RestViewController.h"

@interface MainTableViewController ()

@end

@implementation MainTableViewController

@synthesize mySearchBar, filteredRest, isFiltered;

- (void)viewDidLoad {
    [super viewDidLoad];

    _barButton.target = self.revealViewController;
    _barButton.action = @selector(revealToggle:);

    [self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];

    [self.navigationItem setTitle:@"MadEat"]; /*Cambia el titulo del navigation controller*/

    [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}]; /*Cambia el color de las letras del navigation controller bar del menu principal*/

    [self.navigationController.navigationBar setBarTintColor:[UIColor colorWithRed:27/255.0f green:101/255.0f blue:163/255.0f alpha:1.0f]];

    self.navigationController.navigationBar.tintColor = [UIColor whiteColor]; /*Cambia el color del boton de la izquierda*/

    self.RestTableView.tableFooterView = [[UIView alloc] init]; /*Esta linea hace que en la tabla solo aparezcan el numero de filas que tienes establecidas, es decir, que las vacias no aparezcan*/

    /*Alerta que se muestra solo la primera vez. Está desactivada*/
    if (![@"1" isEqualToString:[[NSUserDefaults standardUserDefaults] objectForKey:@"alert"]]) {
        [[NSUserDefaults standardUserDefaults] setValue:@"1" forKey:@"alert"];
        [[NSUserDefaults standardUserDefaults] synchronize];

        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Terms of use" message:@"The brands mentioned have no relationship with MadEat and the app has no any liability on that content." preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction* ok = [UIAlertAction actionWithTitle:@"Accept" style:UIAlertActionStyleDefault handler:nil];
        [alertController addAction:ok];

        [self presentViewController:alertController animated:YES completion:nil];
    }

    _Title = @[@"80 Grados",
               @"90 Grados",
               @"B&B Babel",
               @"Babelia",
               @"Bacira",
               @"Bar Galleta",
               @"Bar Tomate",
               @"Barra Atlantica",
               @"BaRRa de Pintxos",
               @"BaRRa de Pintxos",];

    _Description = @[@"Barrio Malasaña",
                     @"Barrio Retiro",
                     @"Barrio Chueca",
                     @"Barrio de Salamanca",
                     @"Barrio Chamberí",
                     @"Barrio Malasaña",
                     @"Barrio Chamberí",
                     @"Barrio Malasaña",
                     @"Barrio del Pilar",
                     @"Barrio Retiro",];

    _Images = @[@"80_grados.png",
                @"90_grados",
                @"babel.png",
                @"babelia.png",
                @"bacira.png",
                @"bar_galleta.png",
                @"bar_tomate.png",
                @"barra_atlantica.png",
                @"barra_de_pintxos.png",
                @"barra_de_pintxos.png",];
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{   
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    //return _Title.count;

    if (isFiltered == YES) {
        return filteredRest.count;
    } else {
        return _Title.count;
    }
}    

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"TableCell";
    RestTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...
    if (isFiltered == YES) {
        cell.TitleLabel.text = [filteredRest objectAtIndex:indexPath.row];

    } else {
        int row = [indexPath row];
        cell.TitleLabel.text = _Title[row];
        cell.DescriptionLabel.text = _Description[row];
        cell.RestImage.image = [UIImage imageNamed:_Images[row]];
    }

    cell.RestImage.layer.cornerRadius = 6;
    cell.RestImage.clipsToBounds = YES;
    cell.RestImage.layer.borderWidth = 1;

    return cell;
}

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    /*Cambia el nombre del boton de la izquierda sin afectar al titulo del navigation controller*/
    self.navigationItem.backBarButtonItem=[[UIBarButtonItem alloc] initWithTitle: NSLocalizedString (@"Back", nil) style:UIBarButtonItemStylePlain target:nil action:nil];

    if ([[segue identifier] isEqualToString:@"ShowDetails"]){
        RestViewController *restviewcontroller = [segue destinationViewController];

        NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];

        int row = [myIndexPath row];
        restviewcontroller.DetailModal = @[_Title[row],_Description[row],_Images[row]];

    }
}

-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {

    if (searchText.length == 0) {
        //Set our boolean flag
        isFiltered = NO;
    } else {
        //Set our boolean flag
        isFiltered = YES;
    }
    //Alloc and init our filteredData
    filteredRest = [[NSMutableArray alloc] init];

    for (NSString * restTitle in _Title) {
        NSRange restTitleRange = [restTitle rangeOfString:searchText options:NSCaseInsensitiveSearch];

        if (restTitleRange.location != NSNotFound) {
            [filteredRest addObject:restTitle];
        }
    }

    for (NSString * restDescription in _Description) {
        NSRange restDescriptionRange = [restDescription rangeOfString:searchText options:NSCaseInsensitiveSearch];

        if (restDescriptionRange.location != NSNotFound) {
            //[filteredRest addObject:restDescription];
        }
    }

    for (NSString * restImages in _Images) {
        NSRange restImagesRange = [restImages rangeOfString:searchText options:NSCaseInsensitiveSearch];

        if (restImagesRange.location != NSNotFound) {
            //[filteredRest addObject:restImages];
        }
    }

    //Reload our table view
    [_RestTableView reloadData];
}

-(void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [mySearchBar resignFirstResponder];
}

@end

最后,这是我的TableViewCell.h,名为RestTableViewCell.h

#import <UIKit/UIKit.h>

@interface RestTableViewCell : UITableViewCell

@property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
@property (strong, nonatomic) IBOutlet UILabel *DescriptionLabel;
@property (strong, nonatomic) IBOutlet UIImageView *RestImage;

@end

这是我的问题:

The original TableView The problem filtering by Title

2 个答案:

答案 0 :(得分:2)

显然,您只需将过滤条件应用于Title数组,而不是过滤ImagesDescription数组。

因此,您需要再使用两个NSMutableArray来保存ImagesDescription的过滤结果。

但我建议您为结果构建一个新的Model。示例代码供您参考:

模型层:Restaurant.h

@interface Restaurant : NSObject

@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *desc;
@property (nonatomic, copy) NSString *image;

- (instancetype)init:(NSString *)title descripiton:(NSString *)description image:(NSString *)image;

@end

Restaurant.m

@implementation Restaurant

- (instancetype)init:(NSString *)title descripiton:(NSString *)description image:(NSString *)image {
    self = [super init];
    if (self != nil) {
        self.title = title;
        self.desc = description;
        self.image = image;
    }
    return self;
}

@end

RestViewController.h

@interface RestViewController : UIViewController

@property (nonatomic, strong) Restaurant *DetailModal;

@end

MainTableViewController.m

@interface MainTableViewController ()

@property (nonatomic, strong) NSArray<Restaurant *> *originData;
@property (nonatomic, strong) NSMutableArray<Restaurant *> *filteredRest;
@property (nonatomic, assign) Boolean isFiltered;

@end

@implementation MainTableViewController

@synthesize mySearchBar, filteredRest, isFiltered, originData;

- (void)viewDidLoad {
    [super viewDidLoad];

    originData = @[
                    [[Restaurant alloc] init:@"80 Grados" descripiton:@"Barrio Malasaña" image:@"80_grados.png"],
                    [[Restaurant alloc] init:@"90 Grados" descripiton:@"Barrio Retiro" image:@"90_grados"]
                    ];
    filteredRest = [NSMutableArray new];
    isFiltered = NO;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    //return _Title.count;

    if (isFiltered == YES) {
        return filteredRest.count;
    } else {
        return originData.count;
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"TableCell";
    RestTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    // Configure the cell...
    if (isFiltered == YES) {
        cell.TitleLabel.text = [filteredRest objectAtIndex:indexPath.row].title;
        cell.DescriptionLabel.text = [filteredRest objectAtIndex:indexPath.row].desc;
        cell.RestImage.image = [UIImage imageNamed:[filteredRest objectAtIndex:indexPath.row].image];
    } else {
        cell.TitleLabel.text = [originData objectAtIndex:indexPath.row].title;
        cell.DescriptionLabel.text = [originData objectAtIndex:indexPath.row].desc;
        cell.RestImage.image = [UIImage imageNamed:[originData objectAtIndex:indexPath.row].image];
    }

    cell.RestImage.layer.cornerRadius = 6;
    cell.RestImage.clipsToBounds = YES;
    cell.RestImage.layer.borderWidth = 1;

    return cell;
}

-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    /*Cambia el nombre del boton de la izquierda sin afectar al titulo del navigation controller*/
    self.navigationItem.backBarButtonItem=[[UIBarButtonItem alloc] initWithTitle: NSLocalizedString (@"Back", nil) style:UIBarButtonItemStylePlain target:nil action:nil];

    if ([[segue identifier] isEqualToString:@"ShowDetails"]){
        RestViewController *restviewcontroller = [segue destinationViewController];

        NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];

        if (isFiltered) {
            restviewcontroller.DetailModal = filteredRest[myIndexPath.row];
        } else {
            restviewcontroller.DetailModal = originData[myIndexPath.row];
        }
    }
}

-(void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {

    if (searchText.length == 0) {
        //Set our boolean flag
        isFiltered = NO;
    } else {
        //Set our boolean flag
        isFiltered = YES;
    }
    //Alloc and init our filteredData
    filteredRest = [[NSMutableArray alloc] init];

    for (Restaurant *item in originData) {
        if ([item.title containsString:searchText]) {
            [filteredRest addObject:item];
        }
    }

    //Reload our table view
    [self.tableView reloadData];
}

-(void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {
    [mySearchBar resignFirstResponder];
}

@end

为您的信息构建一个新的model对象是非常有效的,因此您不需要将过滤器应用于三个数组,您只需要搜索一次,结果将保留在一个数组中。

PS:编写OC代码时,还有一个针对编码风格的提示,命名变量,以小写字母开头的对象实例,以及以大写字母命名类是最佳做法。例如,TitleLabel应重命名为titleLabel等等......

答案 1 :(得分:0)

在这里,您正在过滤单元格并重复使用它们。 你只是在替换文字。您还需要替换图像和数据。

if (isFiltered == YES) {
        cell.TitleLabel.text = [filteredRest objectAtIndex:indexPath.row];

} else {
        int row = [indexPath row];
        cell.TitleLabel.text = _Title[row];
        cell.DescriptionLabel.text = _Description[row];
        cell.RestImage.image = [UIImage imageNamed:_Images[row]];
}

我不确定,但我认为你还没有清楚地理解可重复使用细胞的概念。您将重用不在视图中的单元格,这意味着iOS框架将为您提供已经使用过的单元格之一,这样它就不必每次在第一个单元格80Grados的情况下重新创建单元格。

因此,在您收到该单元格后,您将替换标题,但保留所有其他内容。这就是为什么你会看到带有新标题标签的旧内容。

这里需要做的是创建一个包装类,它将包含三个属性text,description和imagefile name。

@class Restaurant
    @property NSString *title;
    @property NString *description;
    @property NSString *image;
@end

将您的逻辑与此结合,而不是将所有数据视为单独的数组。这将非常容易维护。将来,您可以使用来自服务器,用户输入或任何其他方式的数据轻松填写该类。处理3种不同阵列的数据不是很可持续的模型。 因此,创建包装类,通过创建NSMutableArray / NSMutableDictionary来填充数据。而不是放置标题,填充整个包装器对象。

[filteredRest addObject: restaurantObj];

以这种方式更改代码

Restaurant *r;
if (isFiltered == YES) {
        r = [self.filteredRest objectAtIndex:indexPath.row];         
} else {
        r = [self.restaurantList objectAtIndex:indexPath.row]];
} 
cell.TitleLabel.text = r.title;
cell.DescriptionLabel.text = r.description;
cell.RestImage.image =  [UIImage imageNamed:r.image];

如果有任何想法不明确,请告诉我。这只是一个原型,您将不得不在多个地方更改您的代码,但强烈建议您尽快完成这些更改。