在iOS中实现搜索历史记录功能

3
我目前有一个搜索页面,它会为Web服务加载结果列表。但是当我返回到搜索页面时,我想要“保存”输入的任何内容(例如,“resto italian”),然后将该条目和以前的条目显示在下面的表视图中,就像下面的图片一样:
[image]
我的计划是使用属性列表序列化-如果不存在列表,则创建名为history.plist的属性列表,并用每个搜索术语填充它,将最近十个显示在上述表视图中。
我尝试过的方法:
// should create history.plist
- (NSString *)dataFilePath {
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    return [documentsDirectory stringByAppendingString:@"history.plist"];
}

/* This is the action for when 'search' is clicked - calls the method above to create 
a new plist if it's not already created. 
I then try to display the contents of the of the file in the textfield itself 
(for testing purposes) but it's not saving/displaying properly at the moment. */

- (IBAction)saveHistory:(id)sender {        
    NSString *filePath = [self dataFilePath];
    if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
    {
       NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
       for (int i = 0; i < (sizeof(array)); i++) {
            UITextField *theField = self.searchHistory;
            theField.text = [NSString stringWithFormat:@"%@", array];
       }
    }        
    UIApplication *app = [UIApplication sharedApplication];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:app];        
}

任何试图做到这一点的教程链接,对我应该做什么的建议或对我已有内容的改进将不胜感激。

我不会用plist来做这件事(除非有要求)。我相信CoreData在更多排序能力方面速度更快。 - Eric
1
步骤1. 将每个搜索保存为带有时间戳的字符串类型 Core Data。 步骤2. 创建一个tableView,使用 Core Data 获取请求按反向时间顺序填充这些字符串。 步骤3. 为tableView的 didSelectCell 添加一个方法,以便在历史记录字符串中进行重新搜索。我认为每个 Core Data 插入对象只需要字符串和时间戳作为属性。 - Eric
5个回答

0

这应该可以解决问题:

// This is inside viewDidLoad    
UIApplication *myApp = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self     
          selector:@selector(applicationDidEnterBackground:)                                                                
          name:UIApplicationDidEnterBackgroundNotification
          object:myApp];

// This is inside my table view - where I'm loading the file data to display in table cells
NSString *myPath = [self dataFilePath];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
if (fileExists) {
   NSArray *values = [[NSArray alloc] initWithContentsOfFile:myPath];
      for (int i = 0; i < values.count; i++) {
         cell.historyDisplay.text = [NSString stringWithFormat:@"%@", [values objectAtIndex:i]];
      }
}

// This is the file path for history.plist
- (NSString *)dataFilePath {
    NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [[path objectAtIndex:0] stringByAppendingString:@"history.plist"];
}

// This is my search button - I want to save whatever was typed in the text field, into history.plist, to display in my tableview whenever a user goes to it.     
- (IBAction)saveHistory:(id)sender {
    NSMutableArray *values = [[NSMutableArray alloc]initWithContentsOfFile:[self dataFilePath]];
    if(searchInputTextField.text.length > 0)
         [values addObject:searchInputTextField.text];
    [values writeToFile:[self dataFilePath] atomically:YES];    
    [leTableView reloadData];
}

0

我会在评论中提出我的建议,但同时这里有一些对你的代码的编辑,可能会有所帮助。

        NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
        for (int i = 0; i <array.count; i++) {
            //I don't know what this line means
            UITextField *theField = self.searchHistory;
            //Change this line to this
            theField.text = [NSString stringWithFormat:@"%@", [array objectAtIndex:i]];
        }

你应该在这个答案中加入你的建议,这样它们就可以被收集在同一个地方。 - Jonathan Grynspan
我不会使用plist(除非有要求)。我相信CoreData具有更快的排序能力。 - Eric 20分钟前步骤1. 将每个搜索保存为带有时间戳的字符串存储在coreData中。步骤2. 创建一个tableView,使用Core Data Fetch请求以相反的时间顺序填充这些字符串。步骤3. 为tableView添加一个didSelectCell方法,以便在记录的历史字符串上进行重新搜索。我认为每个coreData插入对象只需要字符串和时间戳作为属性。 - Eric
1
我认为,Core Data 的速度只在非常大的数据集上才有意义的提升。对于小型数据集(任何少于几千行左右的数据),编写和读取 plist 文件的开销是可以忽略不计的。 - Jonathan Grynspan
使用plist方法可能可以,但你仍然应该查看我的代码编辑。我认为,与其通过数组索引创建文本字段,不如使用tableView并填充它们是更好的方法。 - Eric

0

请使用以下方法替换您的saveHistory函数:

- (IBAction)saveHistory:(id)sender
{
      NSMutableArray *values = [[NSMutableArray alloc]initWithContentsOfFile:[self dataFilePath]];
      if(searchInputTextField.text.length > 0)
           [values addObject:searchInputTextField.text];
      [values writeToFile:[self dataFilePath] atomically:YES];

      [leTableView reloadData];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
     return values.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     static NSString *CellIdentifier = @"Cell";
     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
     if (cell == nil)
     {
         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
     }
     cell.textLabel.text = [values objectAtIndex:indexPath.row];
}

0

我会使用Core Data,创建一个类,例如HistoryRecord,它包含类型为NSString和NSDate的属性termSearchedtimestamp

#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@interface HistoryRecordManagedObject : NSManagedObject

@property (nonatomic, retain) NSString *termSearched;
@property (nonatomic, retain) NSDate *timestamp;

+ (NSArray *)findEntity:(NSString *)entity withPredicate:(NSPredicate *)predicate

@end

实现

#import "HistoryRecordManagedObject.h"

@implementation HistoryRecordManagedObject

@dynamic termSearched;
@dynamic timstamp;

+ (NSArray *)findEntity:(NSString *)entity withPredicate:(NSPredicate *)predicate
{
    NSError *error;
    NSArray *fetchedObjects;

        /* After set all properties, executes fetch request */
        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
        NSEntityDescription *entityDesc = [NSEntityDescription entityForName:entity
                                                      inManagedObjectContext:managedObjectContext];
        [fetchRequest setEntity:entityDesc];
        [fetchRequest setPredicate:predicate];

        fetchedObjects = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
        [fetchRequest release];


    return fetchedObjects;
}

@end

当然不止这些!使用Core Data还需要完成一些额外的工作,例如创建模型。多了解一些吧!它很值得!

祝好运!


0

在搜索操作中,只需将搜索结果保存到NSUserDefaults。

    NSMutableArray *searches = [[NSUserDefaults standardUserDefaults] arrayForKey:@"searches"];
[searches insertObject:textField.text atIndex:0];
[[NSUserDefaults standardUserDefaults] setObject:searches forKey:@"searches"];
[[NSUserDefaults standardUserDefaults] synchronize];

然后在视图出现时加载相同数组作为表格数据源,并在键盘消失时重新加载表格。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接