TableViewController Vs UIViewController 和里面的 tableView

Posted

技术标签:

【中文标题】TableViewController Vs UIViewController 和里面的 tableView【英文标题】:TableViewController Vs UIViewController and a tableView inside 【发布时间】:2012-11-15 10:37:45 【问题描述】:

我有一个 Master/Details 应用程序。默认情况下,我们将 MasterViewController 附加到 TableViewController,此外,我已将它附加到 Sqlite 数据库,并且所有数据都按应有的方式正确显示。所以我添加了一个 UISearchBar,以便搜索所有项目; 搜索功能工作正常,但唯一的错误是,向下滚动时搜索栏消失。 因此,作为解决方案,我删除了 TableViewController 并创建了一个简单的 UIVIewController 并添加了一个 TableView 、 TableViewCell 和一个搜索栏为了按照许多人的建议将搜索栏固定在视图顶部。现在这两个概念之间的区别在于,一旦应用程序加载,TableViewController(第一种情况)就会在单元格中加载整个数据,当ViewController(第二种情况,带有 tableView、tableViewCell 和 searchBar)在启动时不加载任何内容,当用户开始在 searchBar 中写入单词时,它会加载不同的元素。如何强制 tableView 在启动时加载所有元素,就像你有一个 TableViewCONtroller 一样? 这是我的代码:

//
//  MasterViewController.m

#import "MasterViewController.h"

#import "DetailViewController.h"
#import <sqlite3.h>
#import "Author.h"
@interface MasterViewController ()
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath;
@end

@implementation MasterViewController
NSString *authorNAme , *authorNAme2;

@synthesize tableView;
@synthesize searchWasActive;
@synthesize detailViewController = _detailViewController;
@synthesize fetchedResultsController = __fetchedResultsController;
@synthesize managedObjectContext = __managedObjectContext;
@synthesize theauthors;
NSString *PathDB;


-(BOOL)canBecomeFirstResponder

    return YES;



- (void)awakeFromNib

   // self.clearsSelectionOnViewWillAppear = NO;
    self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
    [super awakeFromNib];


- (void)viewDidLoad


 
   // [self numberOfSectionsInTableView:tableView];


    //[self tableView:tableView willDisplayCell:[self.tableView dequeueReusableCellWithIdentifier:@"Cell"] forRowAtIndexPath:0]; 
    //[self.tableView 

    searchBar.delegate = (id)self;
   // [self.tableView reloadData];

   // [self configureCell:@"Cell" atIndexPath:0];
    [self authorList];
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.navigationItem.leftBarButtonItem = self.editButtonItem;

    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
    self.navigationItem.rightBarButtonItem = addButton;
    self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];


- (void)viewDidUnload



    [self setTableView:nil];
    tableView = nil;
    searchBar = nil;
    [self setSearchWasActive:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    return YES;


- (void)insertNewObject:(id)sender

    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
    NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

    // If appropriate, configure the new managed object.
    // Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template.
    [newManagedObject setValue:[NSDate date] forKey:@"timeStamp"];

    // Save the context.
    NSError *error = nil;
    if (![context save:&error]) 
         // Replace this implementation with code to handle the error appropriately.
         // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    





- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar 
    //[self authorList];
    // [filteredTableData release];

    //[self.tableView reloadData];
    NSLog(@"Cancel Button Clicked");

    // Scroll to top
    [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
    self.searchDisplayController.searchBar.text =@" ";



- (void) searchBarTextDidBeginEditing:(UISearchBar *)sender


    [self.tableView reloadData];
    searchBar.showsCancelButton=NO;




-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
 
    searchBar.showsCancelButton=NO;
    if(text.length == 0)
    
        isFiltered = FALSE;

    
    else
    
        isFiltered = true;
        filteredTableData = [[NSMutableArray alloc] init];

        for (Author* author in theauthors)

          //[NSPredicate predicateWithFormat:@"SELECT * from books where title LIKE %@", searchBar.text];

            NSRange nameRange = [author.name rangeOfString:text options:NSAnchoredSearch];
            NSRange descriptionRange = [author.genre rangeOfString:text options:NSAnchoredSearch];
            if(nameRange.location != NSNotFound || descriptionRange.location != NSNotFound)
            
                [filteredTableData addObject:author];
                NSLog(@"Item Added is %@" , author.name);

            
        
    

    [self.tableView reloadData];







#pragma mark - Table View methods

-(NSMutableArray *) authorList
    [self numberOfSectionsInTableView:tableView];
    theauthors = [[NSMutableArray alloc] initWithCapacity:1000000];
    // NSMutableArray * new2 = [[NSMutableArray alloc ] initWithCapacity:100000];
    // authorNAme = theauthors.sortedArrayHint.description;
    @try 
        NSFileManager *fileMgr = [NSFileManager defaultManager];
        NSLog(@"Before the dbpath variable");
        NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:@"dictionary_native.sqlite"];
        NSLog(@"After the dbpath variable");
        BOOL success = [fileMgr fileExistsAtPath:dbPath];
        if(!success)

        
            NSLog(@"1");
            NSLog(@"Cannot locate database file '%@'.", dbPath);
        
        NSLog(@"Database correctly located");
        if(!(sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK))
        
            NSLog(@"2");
            NSLog(@"An error has occured: %@", sqlite3_errmsg(db));

        
        NSLog(@"Database correctly opened");

        // const char *sql = "SELECT F_Keyword FROM wordss";  
        const char *sql = "SELECT * FROM wordss";

        sqlite3_stmt *sqlStatement;
        if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK)
        
            NSLog(@"Problem with prepare statement:  %@", sqlite3_errmsg(db));
        else
            while (sqlite3_step(sqlStatement)==SQLITE_ROW) 
                //   NSLog(@"entered the while statement");
                Author * author = [[Author alloc] init];

//                //  NSLog(@"Author initialised");
//                
                author.name = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)];
              //  NSLog(@"this is the author.name %@" , author.name);
                author.genre = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 2)];
//                
              //  authorNAme=author.genre;              
//                

                [theauthors addObject:author];




            
            //      authorNAme = author.genre;


        
    
    @catch (NSException *exception) 
        NSLog(@"Problem with prepare statement:  %@", sqlite3_errmsg(db));
    
    @finally 
        //   sqlite3_finalize(sqlStatement);.
        //   authorNAme = nil;

        //   authorNAme = Nil;
        return theauthors;
    








- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView


   // return [[self.fetchedResultsController sections] count];

    return 1;



- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

//    id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
//    return [sectionInfo numberOfObjects];

    int rowCount;
    if(self->isFiltered)
        rowCount = filteredTableData.count;
    else
        rowCount = theauthors.count;
    NSLog(@"This is the number of rows accepted %i" , rowCount);
    return rowCount;



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

  //  UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Cell"];

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];


    if (cell == nil) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
    
    int rowCount = indexPath.row;

    Author *author = [self.theauthors objectAtIndex:rowCount];


    if(isFiltered)
        author = [filteredTableData objectAtIndex:indexPath.row];        

    
    else
        author = [theauthors objectAtIndex:indexPath.row];       
    

    cell.textLabel.text = author.name;


    return cell;


- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath

    // Return NO if you do not want the specified item to be editable.
    return YES;


- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

    if (editingStyle == UITableViewCellEditingStyleDelete) 
        NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
        [context deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];

        NSError *error = nil;
        if (![context save:&error]) 
             // Replace this implementation with code to handle the error appropriately.
             // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        
       


- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath

    // The table view should not be re-orderable.
    return NO;


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

//    NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
//    self.detailViewController.detailItem = object;


   // DetailViewController* vc ;
    MasterViewController *author;
    NSLog(@"This is the showDetailsForIndexPath");
    [self->searchBar resignFirstResponder];
   // Details* vc = [self.storyboard instantiateViewControllerWithIdentifier:@"Details"];
   // AuthorVC* author;

    if(isFiltered)
    
        author = [filteredTableData objectAtIndex:indexPath.row];
    
    else
    
        author = [theauthors objectAtIndex:indexPath.row];
    

    //vc.author = author;
    authorNAme =  author.genre;
    authorNAme2 = author.name ;


   // author = [theauthors objectAtIndex:indexPath.row];

    NSLog(@"This is the author.genre %@" , author.genre);

    //vc.author.genre = author.genre;
    authorNAme =  author.genre;
    authorNAme2 = author.name;

    //NSLog(@"This is the details %@",vc.author.genre);
    NSLog(@"This is the authorNAme Variable %@" , authorNAme);

    self.detailViewController.detailItem = authorNAme;
    self.detailViewController.detailItem2 = authorNAme2;



#pragma mark - Fetched results controller

- (NSFetchedResultsController *)fetchedResultsController

    if (__fetchedResultsController != nil) 
        return __fetchedResultsController;
    

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

    // Set the batch size to a suitable number.
    [fetchRequest setFetchBatchSize:20];

    // Edit the sort key as appropriate.
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    NSError *error = nil;
    if (![self.fetchedResultsController performFetch:&error]) 
         // Replace this implementation with code to handle the error appropriately.
         // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        abort();
    

    return __fetchedResultsController;
    

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller

    [self.tableView beginUpdates];


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type

    switch(type) 
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath

  //  UITableView *tableView = self.tableView;

    switch(type) 
        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
            break;
    


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller

    [self.tableView endUpdates];


/*
// Implementing the above methods to update the table view in response to individual changes may have performance implications if a large number of changes are made simultaneously. If this proves to be an issue, you can instead just implement controllerDidChangeContent: which notifies the delegate that all section and object changes have been processed. 

 - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller

    // In the simplest, most efficient, case, reload the table view.
    [self.tableView reloadData];

 */

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath





//    NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
//    cell.textLabel.text = [[object valueForKey:@"timeStamp"] description];


@end

我们将不胜感激任何帮助...感谢您抽出宝贵时间。

【问题讨论】:

您是否检查了 Delegate 和 Datasource 方法是否正在调用 ie) numberOfRowsInSection、cellForRowAtIndexPath? 我是新手,所以我可能会问一些愚蠢的问题,但如果你能帮忙,我将不胜感激 将 NSLogs 放入这些方法中。 NSLog(@"numberOfRowsInSection 开始") 和 NSLog(@"cellForRowAtIndexPath 开始") 它们不会在启动时被调用,只有当用户在搜索栏中输入时...我如何才能强制它们在启动时被调用? 如果 tableview 在 xib 中,则将其链接到正确的对象并设置委托和数据源。 【参考方案1】:

如果 tableview 在 xib 中,则将其链接到正确的对象并设置委托和数据源。

【讨论】:

谢谢你的解决方案:D

以上是关于TableViewController Vs UIViewController 和里面的 tableView的主要内容,如果未能解决你的问题,请参考以下文章

UICollectionView VS UITableview

透明 UIImageView 在所有 UI 前面

从代码进行故事板 UI 测试

在 iOS 11 上调整 UI 导航

vs2010中修改*.ui文件、替换图片后,不重新生成qrc_*.cpp

VS+Qt QUiLoader动态加载.ui文件