2
0

Persistence fixes and improvements.

[UPDATED]   Pearl to ARC.
[FIXED]     Crash related to persistence changes that caused UI updates
            while other UI changes were ongoing.
[IMPROVED]  Real description of MPElementEntities and use content
            whenever the password is requested.
[IMPROVED]  iOS: Handling of search result fetching and table reloading.
This commit is contained in:
Maarten Billemont
2012-05-07 01:15:19 +02:00
parent f5d9334b06
commit 98080ceb51
9 changed files with 61 additions and 59 deletions

View File

@@ -81,7 +81,8 @@ static NSDictionary *keyHashQuery() {
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator) {
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
// Put concurrency type on main queue, because otherwise updates break updating the search table UI.
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType/*NSPrivateQueueConcurrencyType*/];
_managedObjectContext.persistentStoreCoordinator = coordinator;
[[NSNotificationCenter defaultCenter] addObserverForName:NSPersistentStoreDidImportUbiquitousContentChangesNotification

View File

@@ -30,7 +30,7 @@
- (NSString *)description {
return [[self content] description];
return str(@"%@:%@", [self class], [self name]);
}
- (NSString *)debugDescription {

View File

@@ -121,7 +121,7 @@
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSString *description = [result description];
NSString *description = [result.content description];
[result use];
dispatch_async(dispatch_get_main_queue(), ^{
@@ -143,7 +143,7 @@
element.name = siteName;
element.mpHashHex = [MPAppDelegate get].keyHashHex;
NSString *description = [element description];
NSString *description = [element.content description];
[element use];
dispatch_async(dispatch_get_main_queue(), ^{

View File

@@ -45,7 +45,7 @@
#ifdef DEBUG
[PearlLogger get].autoprintLevel = PearlLogLevelDebug;
// [NSClassFromString(@"WebView") performSelector:NSSelectorFromString(@"_enableRemoteInspector")];
//[NSClassFromString(@"WebView") performSelector:NSSelectorFromString(@"_enableRemoteInspector")];
#endif
}

View File

@@ -177,7 +177,7 @@
self.contentField.text = @"";
if (self.activeElement.name && ![self.activeElement isDeleted])
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSString *description = [self.activeElement description];
NSString *description = [self.activeElement.content description];
dispatch_async(dispatch_get_main_queue(), ^{
self.contentField.text = description;
@@ -343,9 +343,9 @@
- (void)changeElementWithoutWarningDo:(void (^)(void))task; {
// Update element, keeping track of the old password.
NSString *oldPassword = self.activeElement.description;
NSString *oldPassword = [self.activeElement.content description];
task();
NSString *newPassword = self.activeElement.description;
NSString *newPassword = [self.activeElement.content description];
[self updateAnimated:YES];
// Show new and old password.
@@ -461,7 +461,7 @@
[TestFlight passCheckpoint:[NSString stringWithFormat:MPTestFlightCheckpointSelectType, NSStringFromMPElementType(type)]];
if (type & MPElementTypeClassStored && ![self.activeElement.description length])
if (type & MPElementTypeClassStored && ![[self.activeElement.content description] length])
[self showContentTip:@"Tap to set a password." withIcon:self.contentTipEditIcon];
}];
}

View File

@@ -31,10 +31,16 @@
return nil;
self.dateFormatter = [NSDateFormatter new];
self.dateFormatter.timeStyle = NSDateFormatterNoStyle;
self.dateFormatter.dateStyle = NSDateFormatterShortStyle;
self.query = @"";
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass([MPElementEntity class])];
fetchRequest.sortDescriptors = [NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[MPAppDelegate managedObjectContext]
sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController.delegate = self;
return self;
}
@@ -101,31 +107,21 @@
[self update];
return YES;
return NO;
}
- (void)update {
assert(self.query);
assert([MPAppDelegate get].keyHashHex);
NSFetchRequest *fetchRequest = [[MPAppDelegate get].managedObjectModel
fetchRequestFromTemplateWithName:@"MPElements"
substitutionVariables:[NSDictionary dictionaryWithObjectsAndKeys:
self.query, @"query",
[MPAppDelegate get].keyHashHex, @"mpHashHex",
nil]];
[fetchRequest setSortDescriptors:
[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"uses" ascending:NO]]];
self.fetchedResultsController.delegate = nil;
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:[MPAppDelegate managedObjectContext]
sectionNameKeyPath:nil cacheName:nil];
self.fetchedResultsController.delegate = self;
self.fetchedResultsController.fetchRequest.predicate = [NSPredicate predicateWithFormat:@"(%@ == '' OR name BEGINSWITH[cd] %@) AND mpHashHex == %@",
self.query, self.query, [MPAppDelegate get].keyHashHex];
NSError *error;
if (![self.fetchedResultsController performFetch:&error])
err(@"Couldn't fetch elements: %@", error);
[self.searchDisplayController.searchResultsTableView reloadData];
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
@@ -192,8 +188,9 @@
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section < (signed)[[self.fetchedResultsController sections] count])
return (signed)[[[self.fetchedResultsController sections] objectAtIndex:(unsigned)section] numberOfObjects];
NSArray *sections = [self.fetchedResultsController sections];
if (section < (signed)[sections count])
return (signed)[[sections objectAtIndex:(unsigned)section] numberOfObjects];
return 1;
}
@@ -250,28 +247,28 @@
// "New" section.
NSString *siteName = self.query;
[PearlAlert showAlertWithTitle:@"New Site"
message:l(@"Do you want to create a new site named:\n%@", siteName)
viewStyle:UIAlertViewStyleDefault
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (buttonIndex == [alert cancelButtonIndex])
return;
[self.fetchedResultsController.managedObjectContext performBlock:^{
MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPElementGeneratedEntity class])
message:l(@"Do you want to create a new site named:\n%@", siteName)
viewStyle:UIAlertViewStyleDefault
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (buttonIndex == [alert cancelButtonIndex])
return;
[self.fetchedResultsController.managedObjectContext performBlock:^{
MPElementGeneratedEntity *element = [NSEntityDescription insertNewObjectForEntityForName:NSStringFromClass([MPElementGeneratedEntity class])
inManagedObjectContext:self.fetchedResultsController.managedObjectContext];
assert([element isKindOfClass:ClassFromMPElementType((unsigned)element.type)]);
assert([MPAppDelegate get].keyHashHex);
element.name = siteName;
element.mpHashHex = [MPAppDelegate get].keyHashHex;
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate didSelectElement:element];
});
}];
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil];
assert([element isKindOfClass:ClassFromMPElementType((unsigned)element.type)]);
assert([MPAppDelegate get].keyHashHex);
element.name = siteName;
element.mpHashHex = [MPAppDelegate get].keyHashHex;
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate didSelectElement:element];
});
}];
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonYes, nil];
}
}