У меня есть два разных контроллера вида, отображающих почти тот же запрос на выборку. Один из них отображает больше информации, чем другой, а также используется для редактирования данных. Второй - только для отображения.iOS NSFetchedResultsController: Можно ли использовать один и тот же кеш для одной и той же выборки в разных диспетчерах просмотра?
Есть ли способ ускорить процесс, так как оба отображают точно такие же данные? Я ищу что-то в своем коде, что заставляет весь процесс переупорядочивать после отображения второго контроллера представления в первый раз. Другими словами: Изначально переупорядочивание в моем главном контроллере просмотра происходит очень быстро. Затем вы просто показываете второй контроллер вида и переключаетесь обратно, а затем переупорядочивание в главном контроллере просмотра замедляется. У меня есть причина предположить, что это потому, что они используют один и тот же выбор.
Я инициирую запрос выборки как в методах viewDidLoad
, так и в следующих фрагментах кода. Первый один мой главный контроллер представления, а также первый один отображается при запуске приложения:
- (void)setupFetchedResultsController
{
self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MainCategory"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"position" ascending:YES]];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil cacheName:@"MainCategoryCache"];
}
И это мой второй один:
- (void)setupFetchedResultsController
{
self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MainCategory"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"position" ascending:YES]];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:@"NetCache"];
}
Вот вид сделал нагрузки и cellForRowAtIndexPath
из мой основной контроллер вида:
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupFetchedResultsController];
//Edit/Done button
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Edit", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(editTable:)];
[self.navigationItem setRightBarButtonItem:editButton];
//Budget at bottom
self.sumTitleLabel.text = [NSString stringWithFormat:@"%@%@:",NSLocalizedString(@"Budget", nil),NSLocalizedString(@"PerMonth", nil)];
self.sumLabel.text = [[DatabaseFetches budgetPerMonthForManagedObjectContext:self.managedObjectContext] getLocalizedCurrencyString];
//Layout
self.view.backgroundColor = [UIColor clearColor];
[self styleTableView];
[self styleBudgetTotal];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Data model and cell setup
static NSString *CellIdentifier = @"MainCategoryCell";
MainCategoryTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
MainCategory *mainCategory = [self.fetchedResultsController objectAtIndexPath:indexPath];
//Clear background color
cell.backgroundColor = [UIColor clearColor];
//Setup the cell texts
cell.title.text = mainCategory.name;
int numberOfSubcategories = [[mainCategory getNumberOfSpendingCategories] integerValue];
if (numberOfSubcategories == 1) {
cell.subcategories.text = [NSString stringWithFormat:@"%i %@", numberOfSubcategories, NSLocalizedString(@"subcategory", nil)];
} else {
cell.subcategories.text = [NSString stringWithFormat:@"%i %@", numberOfSubcategories, NSLocalizedString(@"subcategories", nil)];
}
cell.costs.text = [[mainCategory getMonthlyCostsOfAllSpendingCategories] getLocalizedCurrencyString];
//Delegation
cell.title.delegate = self;
//Format text
cell.title.font = [Theme tableCellTitleFont];
cell.title.textColor = [Theme tableCellTitleColor];
cell.title.tag = indexPath.row;
cell.subcategories.font = [Theme tableCellSubTitleFont];
cell.subcategories.textColor = [Theme tableCellSubTitleColor];
cell.costs.font = [Theme tableCellValueFont];
cell.costs.textColor = [Theme tableCellValueColor];
//Icon
UIImage *icon;
if(!mainCategory.icon){
icon = [UIImage imageNamed:@"DefaultIcon.png"];
} else {
icon = [UIImage imageNamed:mainCategory.icon];
}
[cell.iconButton setImage:icon forState: UIControlStateNormal];
cell.icon.image = icon;
cell.iconButton.tag = indexPath.row;
//Background image
cell.cellBackground.image = [[UIImage imageNamed:@"content-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
//Selection
//cell.title.highlightedTextColor = cell.title.textColor;
cell.subcategories.highlightedTextColor = cell.subcategories.textColor;
cell.costs.highlightedTextColor = cell.costs.textColor;
return cell;
}
Полный контроллер второго вида:
@interface NetIncomeViewController()
@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
@end
@implementation NetIncomeViewController
@synthesize incomeTitleLabel = _incomeTitleLabel;
@synthesize incomeValueTextField = _incomeValueTextField;
@synthesize incomeBackground = _incomeBackground;
@synthesize incomeValueBackground = _incomeValueBackground;
@synthesize netIncomeTitleLabel = _netIncomeTitleLabel;
@synthesize netIncomeValueLabel = _netIncomeValueLabel;
@synthesize netIncomeBackground = _netIncomeBackground;
@synthesize netIncomeValueBackground = _netIncomeValueBackground;
@synthesize managedObjectContext = _managedObjectContext;
#pragma mark Initializer and view setup
- (void)setupFetchedResultsController
{
self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MainCategory"];
request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"position" ascending:YES]];
self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
}
#pragma mark View lifecycle
- (void)awakeFromNib{
[super awakeFromNib];
//Title (necessary here because otherwise the tab bar would be only localized after first click
//on the respective tab bar and not from beginning
self.title = NSLocalizedString(@"Net Income", nil);
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self updateNetIncome];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupFetchedResultsController];
//Edit/Done button
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Edit", nil) style:UIBarButtonItemStyleBordered target:self action:@selector(editIncome:)];
[self.navigationItem setRightBarButtonItem:editButton];
//Get or set and get the gross income
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSNumber *grossIncome = [defaults objectForKey:@"income"];
if (!grossIncome) {
[defaults setDouble:0 forKey:@"income"];
[defaults synchronize];
grossIncome = [defaults objectForKey:@"income"];
}
self.incomeValueTextField.enabled = NO;
self.incomeValueTextField.delegate = self;
self.incomeValueTextField.keyboardType = UIKeyboardTypeDecimalPad;
self.incomeValueTextField.text = [grossIncome getLocalizedCurrencyString];
[self styleTableViewAndIncome];
}
- (void)styleTableViewAndIncome
{
self.view.backgroundColor = [UIColor clearColor];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.backgroundColor = [UIColor clearColor];
self.incomeTitleLabel.textColor = [Theme budgetValueTitleColor];
self.incomeTitleLabel.font = [Theme budgetValueTitleFont];
self.incomeValueTextField.textColor = [Theme budgetValueColor];
self.incomeValueTextField.font = [Theme budgetValueTitleFont];
self.netIncomeTitleLabel.textColor = [Theme budgetValueTitleColor];
self.netIncomeTitleLabel.font = [Theme budgetValueTitleFont];
self.netIncomeValueLabel.textColor = [Theme budgetValueColor];
self.netIncomeValueLabel.font = [Theme budgetValueFont];
self.incomeTitleLabel.text = [NSString stringWithFormat:@"%@:",NSLocalizedString(@"Income", nil)];
self.netIncomeTitleLabel.text = [NSString stringWithFormat:@"%@%@:",NSLocalizedString(@"Net", nil),NSLocalizedString(@"PerMonth", nil)];
self.incomeBackground.image = [[UIImage imageNamed:@"content-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
self.incomeValueBackground.image = [[UIImage imageNamed:@"price-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
self.netIncomeBackground.image = [[UIImage imageNamed:@"content-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
}
#pragma mark Table view delegate methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"CategoryCostCell";
CategoryCostTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.backgroundColor = [UIColor clearColor];
// Configure the cell layout
MainCategory *mainCategory = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Configure the cell layout
cell.categoryBackground.image = [[UIImage imageNamed:@"content-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
if(!mainCategory.icon){
cell.categoryImage.image = [UIImage imageNamed:@"DefaultIcon.png"];
} else {
cell.categoryImage.image = [UIImage imageNamed:mainCategory.icon];
}
cell.categoryName.text = mainCategory.name;
NSNumber *expenditures = [mainCategory getMonthlyCostsOfAllSpendingCategories];
double expendituresDouble =-[expenditures doubleValue];
if (expendituresDouble == 0) {
expenditures = [NSNumber numberWithDouble: 0];
} else {
expenditures = [NSNumber numberWithDouble: expendituresDouble];
}
cell.categoryCosts.text = [expenditures getLocalizedCurrencyString];
//Format the text
cell.categoryName.font = [Theme tableCellSmallTitleFont];
cell.categoryName.textColor = [Theme tableCellSmallTitleColor];
cell.categoryCosts.font = [Theme tableCellSmallValueFont];
cell.categoryCosts.textColor = [Theme tableCellSmallValueColor];
return cell;
}
#pragma mark TextField delegate methods
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
if(self.editing){
return YES;
} else {
return NO;
}
}
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
textField.text = [NSString stringWithFormat:@"%.2f",[NSNumber getUnLocalizedCurrencyDoubleWithString:textField.text]];
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
textField.text = [[NSNumber numberWithDouble:[textField.text doubleValue]] getLocalizedCurrencyString];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
//Handle the enter button
[textField resignFirstResponder];
[self endEdit];
//Since this method is called AFTER DidEndEditing, we have to call editTable or in this case since we have put all the endEdit code in a seperate method this method directly in order to format the table back from edit mode to normal.
return YES;
}
#pragma mark Edit/Add/Delete action
- (IBAction) editIncome:(id)sender
{
if(self.editing)
{
[self endEdit];
} else {
[self beginEdit];
}
}
- (void) beginEdit
{
//Change to editing mode
[super setEditing:YES animated:YES];
//Exchange the edit button with done button
[self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Done", nil)];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleDone];
self.incomeValueTextField.borderStyle = UITextBorderStyleRoundedRect;
self.incomeValueTextField.enabled = YES;
self.incomeValueBackground.hidden = YES;
self.incomeValueTextField.textColor = [Theme budgetValueTitleColor];
}
- (void) endEdit
{
//Change to editing no
[super setEditing:NO animated:YES];
//Remove Done button and exchange it with edit button
[self.navigationItem.rightBarButtonItem setTitle:NSLocalizedString(@"Edit", nil)];
[self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStylePlain];
self.incomeValueTextField.borderStyle = UITextBorderStyleNone;
self.incomeValueTextField.enabled = NO;
self.incomeValueBackground.hidden = NO;
self.incomeValueTextField.textColor = [Theme budgetValueColor];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setDouble:[NSNumber getUnLocalizedCurrencyDoubleWithString:self.incomeValueTextField.text] forKey:@"income"];
[self updateNetIncome];
//[defaults synchronize];
}
#pragma mark Net income
- (void) updateNetIncome {
double grossIncome = [NSNumber getUnLocalizedCurrencyDoubleWithString:self.incomeValueTextField.text];
double budget = [[DatabaseFetches budgetPerMonthForManagedObjectContext:self.managedObjectContext] doubleValue];
double netIncome = grossIncome - budget;
if(netIncome >0){
self.netIncomeValueBackground.image = [[UIImage imageNamed:@"price-bkg_green"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
} else if(netIncome <0) {
self.netIncomeValueBackground.image = [[UIImage imageNamed:@"price-bkg_red"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
} else {
self.netIncomeValueBackground.image = [[UIImage imageNamed:@"price-bkg"] resizableImageWithCapInsets:UIEdgeInsetsMake(10, 10, 10, 10)];
}
self.netIncomeValueLabel.text = [[NSNumber numberWithDouble:netIncome] getLocalizedCurrencyString];
}
@end
Что вы имеете в виду, когда говорите, что контроллер «замедляется»? Значительно ли отстает таблица? И сколько записей мы говорим здесь? Учитывая эффективность FRC (Fetched Results Controller) при извлечении записей из модели Core Data, я подозреваю, что ваша проблема лежит где-то, кроме запуска второго FRC. –
Да, это заметно заметно. Сейчас у меня всего 3 записи (всего 5 атрибутов, нет только строк и чисел), и он уже отстает. Чем больше я вставляю, тем больше будет отставание. – MichiZH
Тогда это, вероятно, не ваш FRC. Вы делаете что-то необычное с вашим рисунком UITableViewCell? –