我使用的是核心数据和NSFetchedResultsController。有什么可以改进的吗?
//
// RoutineTableViewController.m
// App
//
// Created by Me on 3/21/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "RoutineTableViewController.h"
#import <QuartzCore/QuartzCore.h>
#import "FlurryAnalytics.h"
#import "RoutineDayTableViewController.h"
#import "Routine.h"
#import "Exercise.h"
#import "DataModelController.h"
@implementation RoutineTableViewController
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:YES];
self.fetchedResultsController = nil;
[self.fetchedResultsController performFetch:nil];
[self toggleEditButton];
}
- (void)viewDidLoad {
[super viewDidLoad];
[FlurryAnalytics logEvent:@"Routine"];
if (!self.managedObjectContext) {
self.managedObjectContext = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
self.navigationItem.title = @"Routines";
self.routineTableView.rowHeight = 65;
self.routineTableView.delegate = self;
self.routineTableView.backgroundColor = [UIColor clearColor];
self.view.backgroundColor = [UIColor myBackgroundColor];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(presentCreateRoutineAlert)];
[self toggleEditButton];
}
- (void)toggleEditButton {
if (!self.fetchedResultsController.fetchedObjects.count > 0) {
self.navigationItem.leftBarButtonItem.enabled = NO;
} else {
self.navigationItem.leftBarButtonItem.enabled = YES;
}
}
-(void)presentCreateRoutineAlert {
UIAlertView *anAlert = [[UIAlertView alloc]initWithTitle:@"Add Routine" message:@"Enter name for routine" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Create", nil];
[anAlert setAlertViewStyle:UIAlertViewStylePlainTextInput];
[anAlert show];
}
- (void)alertView:(UIAlertView *)iAlertView willDismissWithButtonIndex:(NSInteger)iButtonIndex {
if (iButtonIndex != [iAlertView cancelButtonIndex]) {
NSString *aRoutineName = [iAlertView textFieldAtIndex:0].text;
[self createRoutineWithName:aRoutineName];
}
}
-(void)createRoutineWithName:(NSString *)iRoutineName {
Routine *aRoutine = [DataModelController createRotuineWithName:iRoutineName];
[self.routineTableView reloadData];
[self pushToListForRoutine:aRoutine];
}
-(void)pushToListForRoutine:(Routine *)iRoutine {
RoutineDayTableViewController *detailViewController = [[RoutineDayTableViewController alloc] initWithNibName:@"RoutineDayTableViewController" bundle:nil withRoutine:iRoutine];
detailViewController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:detailViewController animated:YES];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
cell.imageView.image = [UIImage imageNamed:@"44-shoebox.png"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"newcell.png"]];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.font = [UIFont textLabelFontBig];
Routine *aRoutine = (Routine *)[self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = aRoutine.name;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [self.routineTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)setEditing:(BOOL)editing animated:(BOOL)animate {
[self.routineTableView setEditing: !self.routineTableView.editing animated:YES];
if (self.routineTableView.editing)
[self.navigationItem.leftBarButtonItem setTitle:@"Done"];
else
[self.navigationItem.leftBarButtonItem setTitle:@"Edit"];
}
- (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 (![self.managedObjectContext save:&error]) {
NSLog(@"error: %@", error);
}
}
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Routine *aRoutine = (Routine *)[self.fetchedResultsController objectAtIndexPath:indexPath];
[self pushToListForRoutine:aRoutine];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - Fetched results controller
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Routine" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
NSError *error = nil;
if (![theFetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _fetchedResultsController;
}
#pragma mark - Fetched results controller delegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.routineTableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.routineTableView endUpdates];
[self toggleEditButton];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.routineTableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[self.routineTableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.routineTableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
@end发布于 2013-04-20 22:23:43
简单地看一下表视图控制器代码,我通常会建议一种更有效的配置单元格的方法。你有:
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
cell.imageView.image = [UIImage imageNamed:@"44-shoebox.png"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"newcell.png"]];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.font = [UIFont textLabelFontBig];
Routine *aRoutine = (Routine *)[self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = aRoutine.name;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [self.routineTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}这意味着每次请求单元格时都会运行configureCell:atIndexPath:,每当用户滚动表时就会发生这种情况。这种方法中的大部分工作只需要在创建新单元时才能完成,这在每个用户滚动过程中都不一定发生(因为单元格是循环的)。
..。特别是在这个方法中创建一个新的UIImageView,这是不必要的。看起来只有这一行:
cell.textLabel.text = aRoutine.name;每次请求单元格时都需要运行,因为名称可以更改。因此,我会将代码移出configureCell:atIndexPath:,并将您的代码更改为:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [self.routineTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
[self configureCell:cell atIndexPath:indexPath];
}
// update the cell label for this specific routine name:
Routine *aRoutine = (Routine *)[self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = aRoutine.name;
return cell;
}现在,按照我们使用configureCell:atIndexPath:的方式,将其重命名为initializeCell:atIndexPath:之类可能会更清楚。此外,如果该方法中的代码太多,我可能建议创建一个UITableViewCell的新子类,并将所有这些代码放入其initWithStyle:reuseIdentifier:方法中,这样就可以从表视图控制器中完全删除对configureCell:atIndexPath:的调用。
但是,这将是一个代码模块化/整洁的问题。我提出的关于不每次调用configureCell:atIndexPath:的第一点实际上是一个性能问题。
https://codereview.stackexchange.com/questions/23769
复制相似问题