Avoid using object.managedObjectContext - when no strong reference exists to the MOC, it may yield nil.
[FIXED] Unexpected nil MOCs.
This commit is contained in:
parent
0ee1e176ed
commit
40f34f3d77
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
@required
|
@required
|
||||||
- (NSUInteger)version;
|
- (NSUInteger)version;
|
||||||
- (BOOL)migrateUser:(MPUserEntity *)user;
|
- (BOOL)migrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc;
|
||||||
- (BOOL)migrateElement:(MPElementEntity *)element explicit:(BOOL)explicit;
|
- (BOOL)migrateElement:(MPElementEntity *)element explicit:(BOOL)explicit;
|
||||||
|
|
||||||
- (MPKey *)keyForPassword:(NSString *)password ofUserNamed:(NSString *)userName;
|
- (MPKey *)keyForPassword:(NSString *)password ofUserNamed:(NSString *)userName;
|
||||||
|
@ -31,12 +31,12 @@
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)migrateUser:(MPUserEntity *)user {
|
- (BOOL)migrateUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc {
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
NSFetchRequest *migrationRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
NSFetchRequest *migrationRequest = [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass( [MPElementEntity class] )];
|
||||||
migrationRequest.predicate = [NSPredicate predicateWithFormat:@"version_ < %d AND user == %@", self.version, user];
|
migrationRequest.predicate = [NSPredicate predicateWithFormat:@"version_ < %d AND user == %@", self.version, user];
|
||||||
NSArray *migrationElements = [user.managedObjectContext executeFetchRequest:migrationRequest error:&error];
|
NSArray *migrationElements = [moc executeFetchRequest:migrationRequest error:&error];
|
||||||
if (!migrationElements) {
|
if (!migrationElements) {
|
||||||
err(@"While looking for elements to migrate: %@", error);
|
err(@"While looking for elements to migrate: %@", error);
|
||||||
return NO;
|
return NO;
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
@interface MPAppDelegate_Shared(Key)
|
@interface MPAppDelegate_Shared(Key)
|
||||||
|
|
||||||
- (BOOL)signInAsUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password;
|
- (BOOL)signInAsUser:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password;
|
||||||
- (void)signOutAnimated:(BOOL)animated;
|
- (void)signOutAnimated:(BOOL)animated;
|
||||||
|
|
||||||
- (void)storeSavedKeyFor:(MPUserEntity *)user;
|
- (void)storeSavedKeyFor:(MPUserEntity *)user;
|
||||||
|
@ -77,7 +77,7 @@ static NSDictionary *keyQuery(MPUserEntity *user) {
|
|||||||
[[NSNotificationCenter defaultCenter] postNotificationName:MPSignedOutNotification object:self userInfo:@{ @"animated" : @(animated) }];
|
[[NSNotificationCenter defaultCenter] postNotificationName:MPSignedOutNotification object:self userInfo:@{ @"animated" : @(animated) }];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)signInAsUser:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password {
|
- (BOOL)signInAsUser:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc usingMasterPassword:(NSString *)password {
|
||||||
|
|
||||||
if (password)
|
if (password)
|
||||||
NSAssert(![NSThread isMainThread], @"Computing key may not happen from the main thread.");
|
NSAssert(![NSThread isMainThread], @"Computing key may not happen from the main thread.");
|
||||||
|
@ -493,6 +493,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
|||||||
NSString *uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
NSString *uses = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:2]];
|
||||||
NSString *type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
NSString *type = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:3]];
|
||||||
NSString *version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
NSString *version = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:4]];
|
||||||
|
if ([version length])
|
||||||
|
version = [version substringFromIndex:1]; // Strip the leading colon.
|
||||||
NSString *name = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
NSString *name = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:5]];
|
||||||
NSString *exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
NSString *exportContent = [importedSiteLine substringWithRange:[siteElements rangeAtIndex:6]];
|
||||||
|
|
||||||
@ -509,6 +511,8 @@ PearlAssociatedObjectProperty(NSManagedObjectContext*, MainManagedObjectContext,
|
|||||||
|
|
||||||
[elementsToDelete addObjectsFromArray:existingSites];
|
[elementsToDelete addObjectsFromArray:existingSites];
|
||||||
[importedSiteElements addObject:@[ lastUsed, uses, type, version, name, exportContent ]];
|
[importedSiteElements addObject:@[ lastUsed, uses, type, version, name, exportContent ]];
|
||||||
|
dbg(@"Will import site: lastUsed=%@, uses=%@, type=%@, version=%@, name=%@, exportContent=%@",
|
||||||
|
lastUsed, uses, type, version, name, exportContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,12 +139,13 @@ static OSStatus MPHotKeyHander(EventHandlerCallRef nextHandler, EventRef theEven
|
|||||||
if (sender == self.rememberPasswordItem)
|
if (sender == self.rememberPasswordItem)
|
||||||
[MPConfig get].rememberLogin = [NSNumber numberWithBool:![[MPConfig get].rememberLogin boolValue]];
|
[MPConfig get].rememberLogin = [NSNumber numberWithBool:![[MPConfig get].rememberLogin boolValue]];
|
||||||
if (sender == self.savePasswordItem) {
|
if (sender == self.savePasswordItem) {
|
||||||
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserForThread];
|
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||||
|
MPUserEntity *activeUser = [[MPMacAppDelegate get] activeUserInContext:moc];
|
||||||
if ((activeUser.saveKey = !activeUser.saveKey))
|
if ((activeUser.saveKey = !activeUser.saveKey))
|
||||||
[[MPMacAppDelegate get] storeSavedKeyFor:activeUser];
|
[[MPMacAppDelegate get] storeSavedKeyFor:activeUser];
|
||||||
else
|
else
|
||||||
[[MPMacAppDelegate get] forgetSavedKeyFor:activeUser];
|
[[MPMacAppDelegate get] forgetSavedKeyFor:activeUser];
|
||||||
[activeUser.managedObjectContext saveToStore];
|
[moc saveToStore];
|
||||||
}
|
}
|
||||||
if (sender == self.dialogStyleRegular)
|
if (sender == self.dialogStyleRegular)
|
||||||
[MPMacConfig get].dialogStyleHUD = @NO;
|
[MPMacConfig get].dialogStyleHUD = @NO;
|
||||||
|
@ -256,11 +256,12 @@
|
|||||||
|
|
||||||
- (MPElementEntity *)activeElementForThread {
|
- (MPElementEntity *)activeElementForThread {
|
||||||
|
|
||||||
if (!_activeElementOID)
|
return [self activeElementInContext:[MPMacAppDelegate managedObjectContextForThreadIfReady]];
|
||||||
return nil;
|
}
|
||||||
|
|
||||||
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
- (MPElementEntity *)activeElementInContext:(NSManagedObjectContext *)moc {
|
||||||
if (!moc)
|
|
||||||
|
if (!_activeElementOID)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
NSError *error;
|
NSError *error;
|
||||||
@ -297,9 +298,10 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MPElementEntity *activeElement = [self activeElementForThread];
|
NSManagedObjectContext *moc = [MPMacAppDelegate managedObjectContextForThreadIfReady];
|
||||||
|
MPElementEntity *activeElement = [self activeElementInContext:moc];
|
||||||
[activeElement use];
|
[activeElement use];
|
||||||
[activeElement.managedObjectContext saveToStore];
|
[moc saveToStore];
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch_async( dispatch_get_main_queue(), ^{
|
dispatch_async( dispatch_get_main_queue(), ^{
|
||||||
|
@ -50,6 +50,10 @@
|
|||||||
element.version = MPAlgorithmDefaultVersion;
|
element.version = MPAlgorithmDefaultVersion;
|
||||||
[moc saveToStore];
|
[moc saveToStore];
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
if (element.objectID.isTemporaryID && ![moc obtainPermanentIDsForObjects:@[ element ] error:&error])
|
||||||
|
err(@"Failed to obtain a permanent object ID after creating new element: %@", error);
|
||||||
|
|
||||||
NSManagedObjectID *elementOID = [element objectID];
|
NSManagedObjectID *elementOID = [element objectID];
|
||||||
dispatch_async( dispatch_get_main_queue(), ^{
|
dispatch_async( dispatch_get_main_queue(), ^{
|
||||||
MPElementEntity *element_ = (MPElementEntity *)[[MPiOSAppDelegate managedObjectContextForThreadIfReady]
|
MPElementEntity *element_ = (MPElementEntity *)[[MPiOSAppDelegate managedObjectContextForThreadIfReady]
|
||||||
@ -292,12 +296,18 @@
|
|||||||
forRowAtIndexPath:(NSIndexPath *)indexPath {
|
forRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
|
|
||||||
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
||||||
MPElementEntity *element = [self elementForTableIndexPath:indexPath];
|
NSManagedObjectID *elementOID = [self elementForTableIndexPath:indexPath].objectID;
|
||||||
[element.managedObjectContext performBlockAndWait:^{
|
[MPiOSAppDelegate managedObjectContextPerformBlockAndWait:^(NSManagedObjectContext *context) {
|
||||||
|
NSError *error = nil;
|
||||||
|
MPElementEntity *element = (MPElementEntity *)[context existingObjectWithID:elementOID error:&error];
|
||||||
|
if (!element) {
|
||||||
|
err(@"Failed to retrieve element to delete: %@", error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
inf(@"Deleting element: %@", element.name);
|
inf(@"Deleting element: %@", element.name);
|
||||||
[element.managedObjectContext deleteObject:element];
|
[context deleteObject:element];
|
||||||
[element.managedObjectContext saveToStore];
|
[context saveToStore];
|
||||||
|
|
||||||
MPCheckpoint( MPCheckpointDeleteElement, @{
|
MPCheckpoint( MPCheckpointDeleteElement, @{
|
||||||
@"type" : element.typeName,
|
@"type" : element.typeName,
|
||||||
|
@ -71,7 +71,17 @@
|
|||||||
|
|
||||||
- (IBAction)mail:(UIBarButtonItem *)sender {
|
- (IBAction)mail:(UIBarButtonItem *)sender {
|
||||||
|
|
||||||
[[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self];
|
if ([[MPiOSConfig get].traceMode boolValue]) {
|
||||||
|
[PearlAlert showAlertWithTitle:@"Hiding Trace Messages" message:
|
||||||
|
@"Trace-level log messages will not be mailed. "
|
||||||
|
@"These messages contain sensitive and personal information."
|
||||||
|
viewStyle:UIAlertViewStyleDefault initAlert:nil
|
||||||
|
tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||||
|
[[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self];
|
||||||
|
} cancelTitle:[PearlStrings get].commonButtonOkay otherTitles:nil];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
[[MPiOSAppDelegate get] openFeedbackWithLogs:YES forVC:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -146,15 +146,15 @@
|
|||||||
|
|
||||||
// Needed for when we appear after a modal VC dismisses:
|
// Needed for when we appear after a modal VC dismisses:
|
||||||
// We can't present until the other modal VC has been fully dismissed and presenting in -viewWillAppear: will fail.
|
// We can't present until the other modal VC has been fully dismissed and presenting in -viewWillAppear: will fail.
|
||||||
dispatch_async( dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0 ), ^{
|
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||||
if ([MPAlgorithmDefault migrateUser:activeUser] && !self.suppressOutdatedAlert)
|
if ([MPAlgorithmDefault migrateUser:activeUser inContext:moc] && !self.suppressOutdatedAlert)
|
||||||
[UIView animateWithDuration:0.3f animations:^{
|
[UIView animateWithDuration:0.3f animations:^{
|
||||||
self.outdatedAlertContainer.alpha = 1;
|
self.outdatedAlertContainer.alpha = 1;
|
||||||
self.suppressOutdatedAlert = YES;
|
self.suppressOutdatedAlert = YES;
|
||||||
}];
|
}];
|
||||||
[activeUser.managedObjectContext saveToStore];
|
[moc saveToStore];
|
||||||
} );
|
}];
|
||||||
|
|
||||||
if (![[MPiOSConfig get].actionsTipShown boolValue])
|
if (![[MPiOSConfig get].actionsTipShown boolValue])
|
||||||
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
|
[UIView animateWithDuration:animated? 0.3f: 0 animations:^{
|
||||||
@ -506,7 +506,7 @@
|
|||||||
@"If you continue, a new password will be generated for this site. "
|
@"If you continue, a new password will be generated for this site. "
|
||||||
@"You will then need to update your account's old password to this newly generated password.\n\n"
|
@"You will then need to update your account's old password to this newly generated password.\n\n"
|
||||||
@"You can reset the counter by holding down on this button."
|
@"You can reset the counter by holding down on this button."
|
||||||
do:^BOOL(MPElementEntity *activeElement) {
|
do:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||||
if (![activeElement isKindOfClass:[MPElementGeneratedEntity class]]) {
|
if (![activeElement isKindOfClass:[MPElementGeneratedEntity class]]) {
|
||||||
// Not of a type that supports a password counter.
|
// Not of a type that supports a password counter.
|
||||||
err(@"Cannot increment password counter: Element is not generated: %@", activeElement.name);
|
err(@"Cannot increment password counter: Element is not generated: %@", activeElement.name);
|
||||||
@ -545,7 +545,7 @@
|
|||||||
@"You are resetting the site's password counter.\n\n"
|
@"You are resetting the site's password counter.\n\n"
|
||||||
@"If you continue, the site's password will change back to its original value. "
|
@"If you continue, the site's password will change back to its original value. "
|
||||||
@"You will then need to update your account's password back to this original value."
|
@"You will then need to update your account's password back to this original value."
|
||||||
do:^BOOL(MPElementEntity *activeElement_) {
|
do:^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) {
|
||||||
inf(@"Resetting password counter for: %@", activeElement_.name);
|
inf(@"Resetting password counter for: %@", activeElement_.name);
|
||||||
((MPElementGeneratedEntity *)activeElement_).counter = 1;
|
((MPElementGeneratedEntity *)activeElement_).counter = 1;
|
||||||
|
|
||||||
@ -576,7 +576,8 @@
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)changeActiveElementWithWarning:(NSString *)warning do:(BOOL (^)(MPElementEntity *activeElement))task; {
|
- (void)changeActiveElementWithWarning:(NSString *)warning
|
||||||
|
do:(BOOL (^)(MPElementEntity *activeElement, NSManagedObjectContext *context))task {
|
||||||
|
|
||||||
[PearlAlert showAlertWithTitle:@"Password Change" message:warning viewStyle:UIAlertViewStyleDefault
|
[PearlAlert showAlertWithTitle:@"Password Change" message:warning viewStyle:UIAlertViewStyleDefault
|
||||||
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
initAlert:nil tappedButtonBlock:^(UIAlertView *alert, NSInteger buttonIndex) {
|
||||||
@ -587,7 +588,7 @@
|
|||||||
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
} cancelTitle:[PearlStrings get].commonButtonCancel otherTitles:[PearlStrings get].commonButtonContinue, nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)changeActiveElementWithoutWarningDo:(BOOL (^)(MPElementEntity *activeElement))task; {
|
- (void)changeActiveElementWithoutWarningDo:(BOOL (^)(MPElementEntity *, NSManagedObjectContext *context))task {
|
||||||
|
|
||||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
|
||||||
MPElementEntity *activeElement = [self activeElementInContext:context];
|
MPElementEntity *activeElement = [self activeElementInContext:context];
|
||||||
@ -595,7 +596,7 @@
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
NSString *oldPassword = [activeElement.content description];
|
NSString *oldPassword = [activeElement.content description];
|
||||||
if (!task( activeElement ))
|
if (!task( activeElement, context ))
|
||||||
return;
|
return;
|
||||||
NSString *newPassword = [activeElement.content description];
|
NSString *newPassword = [activeElement.content description];
|
||||||
|
|
||||||
@ -669,7 +670,7 @@
|
|||||||
@"This upgrade improves the site's compatibility with the latest version of Master Password.";
|
@"This upgrade improves the site's compatibility with the latest version of Master Password.";
|
||||||
|
|
||||||
[self changeActiveElementWithWarning:warning do:
|
[self changeActiveElementWithWarning:warning do:
|
||||||
^BOOL(MPElementEntity *activeElement_) {
|
^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) {
|
||||||
inf(@"Explicitly migrating element: %@", activeElement_);
|
inf(@"Explicitly migrating element: %@", activeElement_);
|
||||||
[activeElement_ migrateExplicitly:YES];
|
[activeElement_ migrateExplicitly:YES];
|
||||||
|
|
||||||
@ -785,12 +786,12 @@
|
|||||||
@"You are about to change the type of this password.\n\n"
|
@"You are about to change the type of this password.\n\n"
|
||||||
@"If you continue, the password for this site will change. "
|
@"If you continue, the password for this site will change. "
|
||||||
@"You will need to update your account's old password to the new one."
|
@"You will need to update your account's old password to the new one."
|
||||||
do:^BOOL(MPElementEntity *activeElement) {
|
do:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||||
if ([activeElement.algorithm classOfType:type] != activeElement.typeClass) {
|
if ([activeElement.algorithm classOfType:type] != activeElement.typeClass) {
|
||||||
// Type requires a different class of element. Recreate the element.
|
// Type requires a different class of element. Recreate the element.
|
||||||
MPElementEntity *newElement
|
MPElementEntity *newElement
|
||||||
= [NSEntityDescription insertNewObjectForEntityForName:[activeElement.algorithm classNameOfType:type]
|
= [NSEntityDescription insertNewObjectForEntityForName:[activeElement.algorithm classNameOfType:type]
|
||||||
inManagedObjectContext:activeElement.managedObjectContext];
|
inManagedObjectContext:context];
|
||||||
newElement.name = activeElement.name;
|
newElement.name = activeElement.name;
|
||||||
newElement.user = activeElement.user;
|
newElement.user = activeElement.user;
|
||||||
newElement.uses = activeElement.uses;
|
newElement.uses = activeElement.uses;
|
||||||
@ -798,11 +799,10 @@
|
|||||||
newElement.version = activeElement.version;
|
newElement.version = activeElement.version;
|
||||||
newElement.loginName = activeElement.loginName;
|
newElement.loginName = activeElement.loginName;
|
||||||
|
|
||||||
[activeElement.managedObjectContext deleteObject:activeElement];
|
[context deleteObject:activeElement];
|
||||||
|
|
||||||
NSError *error;
|
NSError *error;
|
||||||
if (![newElement.managedObjectContext obtainPermanentIDsForObjects:@[ newElement ]
|
if (![context obtainPermanentIDsForObjects:@[ newElement ] error:&error])
|
||||||
error:&error])
|
|
||||||
err(@"Failed to obtain a permanent object ID after changing object type: %@", error);
|
err(@"Failed to obtain a permanent object ID after changing object type: %@", error);
|
||||||
|
|
||||||
_activeElementOID = newElement.objectID;
|
_activeElementOID = newElement.objectID;
|
||||||
@ -819,15 +819,11 @@
|
|||||||
- (void)didSelectElement:(MPElementEntity *)element {
|
- (void)didSelectElement:(MPElementEntity *)element {
|
||||||
|
|
||||||
inf(@"Selected: %@", element.name);
|
inf(@"Selected: %@", element.name);
|
||||||
NSError *error = nil;
|
|
||||||
if (element.objectID.isTemporaryID && ![element.managedObjectContext obtainPermanentIDsForObjects:@[ element ] error:&error])
|
|
||||||
err(@"Failed to obtain a permanent object ID after setting active element: %@", error);
|
|
||||||
|
|
||||||
_activeElementOID = element.objectID;
|
_activeElementOID = element.objectID;
|
||||||
[self closeAlert];
|
[self closeAlert];
|
||||||
|
|
||||||
if (element) {
|
if (element) {
|
||||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement) {
|
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||||
if ([activeElement use] == 1)
|
if ([activeElement use] == 1)
|
||||||
[self showAlertWithTitle:@"New Site" message:
|
[self showAlertWithTitle:@"New Site" message:
|
||||||
PearlString( @"You've just created a password for %@.\n\n"
|
PearlString( @"You've just created a password for %@.\n\n"
|
||||||
@ -890,7 +886,7 @@
|
|||||||
// Content hasn't changed.
|
// Content hasn't changed.
|
||||||
return;
|
return;
|
||||||
|
|
||||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement_) {
|
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement_, NSManagedObjectContext *context) {
|
||||||
((MPElementStoredEntity *)activeElement_).content = self.contentField.text;
|
((MPElementStoredEntity *)activeElement_).content = self.contentField.text;
|
||||||
return YES;
|
return YES;
|
||||||
}];
|
}];
|
||||||
@ -903,7 +899,7 @@
|
|||||||
[MPiOSConfig get].loginNameTipShown = @YES;
|
[MPiOSConfig get].loginNameTipShown = @YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement) {
|
[self changeActiveElementWithoutWarningDo:^BOOL(MPElementEntity *activeElement, NSManagedObjectContext *context) {
|
||||||
if ([self.loginNameField.text length])
|
if ([self.loginNameField.text length])
|
||||||
activeElement.loginName = self.loginNameField.text;
|
activeElement.loginName = self.loginNameField.text;
|
||||||
else
|
else
|
||||||
|
@ -47,9 +47,13 @@
|
|||||||
} options:0];
|
} options:0];
|
||||||
[avatar onSelect:^(BOOL selected) {
|
[avatar onSelect:^(BOOL selected) {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||||
|
if (!moc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||||
activeUser.avatar = (unsigned)avatar.tag;
|
activeUser.avatar = (unsigned)avatar.tag;
|
||||||
[activeUser.managedObjectContext saveToStore];
|
[moc saveToStore];
|
||||||
}
|
}
|
||||||
} options:0];
|
} options:0];
|
||||||
avatar.selected = (a == [[MPiOSAppDelegate get] activeUserForThread].avatar);
|
avatar.selected = (a == [[MPiOSAppDelegate get] activeUserForThread].avatar);
|
||||||
@ -129,8 +133,12 @@
|
|||||||
[[MPiOSAppDelegate get] export];
|
[[MPiOSAppDelegate get] export];
|
||||||
|
|
||||||
else if (cell == self.changeMPCell) {
|
else if (cell == self.changeMPCell) {
|
||||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||||
[[MPiOSAppDelegate get] changeMasterPasswordFor:activeUser inContext:activeUser.managedObjectContext didResetBlock:nil];
|
if (!moc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||||
|
[[MPiOSAppDelegate get] changeMasterPasswordFor:activeUser saveInContext:moc didResetBlock:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||||
@ -140,9 +148,13 @@
|
|||||||
|
|
||||||
- (void)didSelectType:(MPElementType)type {
|
- (void)didSelectType:(MPElementType)type {
|
||||||
|
|
||||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||||
|
if (!moc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||||
activeUser.defaultType = type;
|
activeUser.defaultType = type;
|
||||||
[activeUser.managedObjectContext saveToStore];
|
[moc saveToStore];
|
||||||
|
|
||||||
self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:activeUser.defaultType];
|
self.defaultTypeLabel.text = [[MPiOSAppDelegate get].key.algorithm shortNameOfType:activeUser.defaultType];
|
||||||
}
|
}
|
||||||
@ -156,12 +168,16 @@
|
|||||||
|
|
||||||
- (IBAction)didToggleSwitch:(UISwitch *)sender {
|
- (IBAction)didToggleSwitch:(UISwitch *)sender {
|
||||||
|
|
||||||
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserForThread];
|
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||||
|
if (!moc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:moc];
|
||||||
if ((activeUser.saveKey = sender.on))
|
if ((activeUser.saveKey = sender.on))
|
||||||
[[MPiOSAppDelegate get] storeSavedKeyFor:activeUser];
|
[[MPiOSAppDelegate get] storeSavedKeyFor:activeUser];
|
||||||
else
|
else
|
||||||
[[MPiOSAppDelegate get] forgetSavedKeyFor:activeUser];
|
[[MPiOSAppDelegate get] forgetSavedKeyFor:activeUser];
|
||||||
[activeUser.managedObjectContext saveToStore];
|
[moc saveToStore];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -345,20 +345,19 @@
|
|||||||
|
|
||||||
[self.avatarToUserOID setObject:NilToNSNull([user objectID]) forKey:[NSValue valueWithNonretainedObject:avatar]];
|
[self.avatarToUserOID setObject:NilToNSNull([user objectID]) forKey:[NSValue valueWithNonretainedObject:avatar]];
|
||||||
|
|
||||||
if ([_selectedUserOID isEqual:[user objectID]]) {
|
if ([_selectedUserOID isEqual:[user objectID]])
|
||||||
self.selectedUser = user;
|
|
||||||
avatar.selected = YES;
|
avatar.selected = YES;
|
||||||
}
|
|
||||||
|
|
||||||
return avatar;
|
return avatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didToggleUserSelection {
|
- (void)didToggleUserSelection {
|
||||||
|
|
||||||
MPUserEntity *selectedUser = [self selectedUserForThread];
|
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||||
|
MPUserEntity *selectedUser = [self selectedUserInContext:moc];
|
||||||
if (!selectedUser)
|
if (!selectedUser)
|
||||||
[self.passwordField resignFirstResponder];
|
[self.passwordField resignFirstResponder];
|
||||||
else if ([[MPiOSAppDelegate get] signInAsUser:selectedUser inContext:selectedUser.managedObjectContext usingMasterPassword:nil]) {
|
else if ([[MPiOSAppDelegate get] signInAsUser:selectedUser saveInContext:moc usingMasterPassword:nil]) {
|
||||||
[self performSegueWithIdentifier:@"MP_Unlock" sender:self];
|
[self performSegueWithIdentifier:@"MP_Unlock" sender:self];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -450,7 +449,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Confirm
|
// Confirm
|
||||||
[moc saveToStore];
|
[moc performBlockAndWait:^{
|
||||||
|
[moc saveToStore];
|
||||||
|
NSError *error = nil;
|
||||||
|
if (![moc obtainPermanentIDsForObjects:@[newUser] error:&error])
|
||||||
|
err(@"Failed to obtain permanent object ID for new user: %@", error);
|
||||||
|
}];
|
||||||
completion( YES );
|
completion( YES );
|
||||||
|
|
||||||
[self updateUsers];
|
[self updateUsers];
|
||||||
@ -535,7 +539,7 @@
|
|||||||
UIButton *targetedAvatar = selectedAvatar;
|
UIButton *targetedAvatar = selectedAvatar;
|
||||||
if (!targetedAvatar) {
|
if (!targetedAvatar) {
|
||||||
targetedAvatar = [self findTargetedAvatar];
|
targetedAvatar = [self findTargetedAvatar];
|
||||||
targetedUser = [self userForAvatar:targetedAvatar];
|
targetedUser = [self userForAvatar:targetedAvatar inContext:[MPiOSAppDelegate managedObjectContextForThreadIfReady]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
[self.avatarsView enumerateSubviews:^(UIView *subview, BOOL *stop, BOOL *recurse) {
|
||||||
@ -619,7 +623,7 @@
|
|||||||
[self setSpinnerActive:YES];
|
[self setSpinnerActive:YES];
|
||||||
|
|
||||||
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
[MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *moc) {
|
||||||
BOOL unlocked = [[MPiOSAppDelegate get] signInAsUser:[self selectedUserInContext:moc] inContext:moc
|
BOOL unlocked = [[MPiOSAppDelegate get] signInAsUser:[self selectedUserInContext:moc] saveInContext:moc
|
||||||
usingMasterPassword:self.passwordField.text];
|
usingMasterPassword:self.passwordField.text];
|
||||||
|
|
||||||
dispatch_async( dispatch_get_main_queue(), ^{
|
dispatch_async( dispatch_get_main_queue(), ^{
|
||||||
@ -656,11 +660,7 @@
|
|||||||
return avatar;
|
return avatar;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (MPUserEntity *)userForAvatar:(UIButton *)avatar {
|
- (MPUserEntity *)userForAvatar:(UIButton *)avatar inContext:(NSManagedObjectContext *)moc {
|
||||||
|
|
||||||
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
|
||||||
if (!moc)
|
|
||||||
return nil;
|
|
||||||
|
|
||||||
NSManagedObjectID *userOID = NSNullToNil([self.avatarToUserOID objectForKey:[NSValue valueWithNonretainedObject:avatar]]);
|
NSManagedObjectID *userOID = NSNullToNil([self.avatarToUserOID objectForKey:[NSValue valueWithNonretainedObject:avatar]]);
|
||||||
if (!userOID)
|
if (!userOID)
|
||||||
@ -984,11 +984,11 @@
|
|||||||
if ([self selectedUserForThread])
|
if ([self selectedUserForThread])
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MPUserEntity *targetedUser = [self userForAvatar:[self findTargetedAvatar]];
|
NSManagedObjectContext *moc = [MPiOSAppDelegate managedObjectContextForThreadIfReady];
|
||||||
|
MPUserEntity *targetedUser = [self userForAvatar:[self findTargetedAvatar] inContext:moc];
|
||||||
if (!targetedUser)
|
if (!targetedUser)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
NSManagedObjectContext *moc = targetedUser.managedObjectContext;
|
|
||||||
[PearlSheet showSheetWithTitle:targetedUser.name
|
[PearlSheet showSheetWithTitle:targetedUser.name
|
||||||
viewStyle:UIActionSheetStyleBlackTranslucent
|
viewStyle:UIActionSheetStyleBlackTranslucent
|
||||||
initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {
|
initSheet:nil tappedButtonBlock:^(UIActionSheet *sheet, NSInteger buttonIndex) {
|
||||||
@ -1008,7 +1008,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (buttonIndex == [sheet firstOtherButtonIndex])
|
if (buttonIndex == [sheet firstOtherButtonIndex])
|
||||||
[[MPiOSAppDelegate get] changeMasterPasswordFor:targetedUser inContext:moc didResetBlock:^{
|
[[MPiOSAppDelegate get] changeMasterPasswordFor:targetedUser saveInContext:moc didResetBlock:^{
|
||||||
dispatch_async( dispatch_get_main_queue(), ^{
|
dispatch_async( dispatch_get_main_queue(), ^{
|
||||||
[[self avatarForUser:targetedUser] setSelected:YES];
|
[[self avatarForUser:targetedUser] setSelected:YES];
|
||||||
} );
|
} );
|
||||||
|
@ -20,6 +20,6 @@
|
|||||||
- (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController;
|
- (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController;
|
||||||
|
|
||||||
- (void)export;
|
- (void)export;
|
||||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset;
|
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -470,9 +470,9 @@
|
|||||||
- (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController {
|
- (void)openFeedbackWithLogs:(BOOL)logs forVC:(UIViewController *)viewController {
|
||||||
|
|
||||||
NSString *userName = [[MPiOSAppDelegate get] activeUserForThread].name;
|
NSString *userName = [[MPiOSAppDelegate get] activeUserForThread].name;
|
||||||
PearlLogLevel logLevel = [[MPiOSConfig get].sendInfo boolValue]? PearlLogLevelDebug: PearlLogLevelInfo;
|
PearlLogLevel logLevel = PearlLogLevelInfo;
|
||||||
if ([[MPiOSConfig get].traceMode boolValue])
|
if (logs && ([[MPiOSConfig get].sendInfo boolValue] || [[MPiOSConfig get].traceMode boolValue]))
|
||||||
logLevel = PearlLogLevelTrace;
|
logLevel = PearlLogLevelDebug;
|
||||||
|
|
||||||
[[[PearlEMail alloc] initForEMailTo:@"Master Password Development <masterpassword@lyndir.com>"
|
[[[PearlEMail alloc] initForEMailTo:@"Master Password Development <masterpassword@lyndir.com>"
|
||||||
subject:PearlString( @"Feedback for Master Password [%@]",
|
subject:PearlString( @"Feedback for Master Password [%@]",
|
||||||
@ -567,7 +567,7 @@
|
|||||||
nil];
|
nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)changeMasterPasswordFor:(MPUserEntity *)user inContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset {
|
- (void)changeMasterPasswordFor:(MPUserEntity *)user saveInContext:(NSManagedObjectContext *)moc didResetBlock:(void (^)(void))didReset {
|
||||||
|
|
||||||
[PearlAlert showAlertWithTitle:@"Changing Master Password"
|
[PearlAlert showAlertWithTitle:@"Changing Master Password"
|
||||||
message:
|
message:
|
||||||
|
@ -492,28 +492,28 @@ Your passwords will be AES-encrypted with your master password.</string>
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="372"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="372"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||||
<mutableString key="text">119-20:51:52 MPiOSAppDelegate.m:36 | INFO : Initializing TestFlight
|
<string key="text">119-20:51:52 MPiOSAppDelegate.m:36 | INFO : Initializing TestFlight
|
||||||
119-20:51:52 MPiOSAppDelegate.m:70 | INFO : Initializing Google+
|
119-20:51:52 MPiOSAppDelegate.m:70 | INFO : Initializing Google+
|
||||||
119-20:51:52 MPiOSAppDelegate.m:80 | INFO : Initializing Crashlytics
|
119-20:51:52 MPiOSAppDelegate.m:80 | INFO : Initializing Crashlytics
|
||||||
119-20:51:52 MPiOSAppDelegate.m:109 | INFO : Initializing Localytics
|
119-20:51:52 MPiOSAppDelegate.m:109 | INFO : Initializing Localytics
|
||||||
119-20:51:53 PearlAppDelegate.m:71 | INFO : Master Password (MasterPassword) 1.4 (1.4.0) (GIT: 1.4-0-g8a4eecd-dirty)
|
119-20:51:53 PearlAppDelegate.m:71 | INFO : Master Password (MasterPassword) 1.4 (1.4.0) (GIT: 1.4-0-g8a4eecd-dirty)
|
||||||
119-20:51:53 MPiOSAppDelegate.m:257 | INFO : Started up with device identifier: A8C51CDA-6F60-4F0C-BFC9-68A08F2F2DD7
|
119-20:51:53 MPiOSAppDelegate.m:257 | INFO : Started up with device identifier: A8C51CDA-6F60-4F0C-BFC9-68A08F2F2DD7
|
||||||
119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] (Re)loading store...
|
119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] (Re)loading store...
|
||||||
119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Will load cloud store: 0B3CA2DF-5796-44DF-B5E0-121EC3846464 (definite).
|
119-20:51:59 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Will load cloud store: 0B3CA2DF-5796-44DF-B5E0-121EC3846464 (definite).
|
||||||
119-20:51:59 PearlConfig.m:193 | INFO : Lock screen will appear
|
119-20:51:59 PearlConfig.m:193 | INFO : Lock screen will appear
|
||||||
119-20:51:59 MPiOSAppDelegate.m:412 | INFO : Re-activated
|
119-20:51:59 MPiOSAppDelegate.m:412 | INFO : Re-activated
|
||||||
119-20:51:59 PearlConfig.m:180 | DEBUG : MPiOSConfig.launchCount = [70 ->] 71
|
119-20:51:59 PearlConfig.m:180 | DEBUG : MPiOSConfig.launchCount = [70 ->] 71
|
||||||
119-20:52:02 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Clearing stores...
|
119-20:52:02 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Clearing stores...
|
||||||
119-20:52:03 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Loading store without seeding.
|
119-20:52:03 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Loading store without seeding.
|
||||||
119-20:52:09 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Cloud enabled and successfully loaded cloud store.
|
119-20:52:09 MPAppDelegate_Store.m:278 | DEBUG : [StoreManager] Cloud enabled and successfully loaded cloud store.
|
||||||
119-20:52:09 MPAppDelegate_Store.m:299 | INFO : Using iCloud? 1
|
119-20:52:09 MPAppDelegate_Store.m:299 | INFO : Using iCloud? 1
|
||||||
119-20:52:12 MPAppDelegate_Key.m:28 | INFO : Found key in keychain for: b55911588b178466be1d6392597e899b8de46f9a
|
119-20:52:12 MPAppDelegate_Key.m:28 | INFO : Found key in keychain for: b55911588b178466be1d6392597e899b8de46f9a
|
||||||
119-20:52:12 MPAppDelegate_Key.m:132 | INFO : Logged in: b55911588b178466be1d6392597e899b8de46f9a
|
119-20:52:12 MPAppDelegate_Key.m:132 | INFO : Logged in: b55911588b178466be1d6392597e899b8de46f9a
|
||||||
119-20:52:13 MPUnlockViewController.m:229 | INFO : Lock screen will disappear
|
119-20:52:13 MPUnlockViewController.m:229 | INFO : Lock screen will disappear
|
||||||
119-20:52:13 MPMainViewController.m:142 | INFO : Main will appear
|
119-20:52:13 MPMainViewController.m:142 | INFO : Main will appear
|
||||||
119-20:52:16 MPMainViewController.m:734 | INFO : Action: Preferences
|
119-20:52:16 MPMainViewController.m:734 | INFO : Action: Preferences
|
||||||
119-20:52:17 MPMainViewController.m:187 | INFO : Main will disappear.
|
119-20:52:17 MPMainViewController.m:187 | INFO : Main will disappear.
|
||||||
</mutableString>
|
</string>
|
||||||
<color key="textColor" cocoaTouchSystemColor="lightTextColor"/>
|
<color key="textColor" cocoaTouchSystemColor="lightTextColor"/>
|
||||||
<fontDescription key="fontDescription" name="AmericanTypewriter" family="American Typewriter" pointSize="9"/>
|
<fontDescription key="fontDescription" name="AmericanTypewriter" family="American Typewriter" pointSize="9"/>
|
||||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||||
@ -2916,6 +2916,204 @@ However, it means that anyone who finds your device unlocked can do the same.</s
|
|||||||
<image name="ui_textfield.png" width="158" height="34"/>
|
<image name="ui_textfield.png" width="158" height="34"/>
|
||||||
<image name="unlocked.png" width="84" height="80"/>
|
<image name="unlocked.png" width="84" height="80"/>
|
||||||
</resources>
|
</resources>
|
||||||
|
<classes>
|
||||||
|
<class className="IASKAppSettingsViewController" superclassName="UITableViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/IASKAppSettingsViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="outlet" name="delegate"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPAppViewController" superclassName="UIViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPAppViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="action" name="deblock:" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="action" name="gorillas:" candidateClass="UIButton"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPAppsViewController" superclassName="UIViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPAppsViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="action" name="exit"/>
|
||||||
|
<relationship kind="outlet" name="pagePositionView" candidateClass="UIImageView"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPElementListAllViewController" superclassName="MPElementListController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPElementListAllViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="action" name="add:"/>
|
||||||
|
<relationship kind="action" name="close:"/>
|
||||||
|
<relationship kind="outlet" name="navigationBar" candidateClass="UINavigationBar"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPElementListController" superclassName="UITableViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPElementListController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="outlet" name="delegate"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPElementListSearchController" superclassName="MPElementListController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPElementListSearchController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="outlet" name="searchDisplayController" candidateClass="UISearchDisplayController"/>
|
||||||
|
<relationship kind="outlet" name="searchTipContainer" candidateClass="UIView"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPGuideViewController" superclassName="UIViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPGuideViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="action" name="close"/>
|
||||||
|
<relationship kind="action" name="play"/>
|
||||||
|
<relationship kind="outlet" name="content" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="contentButton" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="contentText" candidateClass="UITextField"/>
|
||||||
|
<relationship kind="outlet" name="contentTip" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="contentTipText" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="largePlayButton" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="progress" candidateClass="UIProgressView"/>
|
||||||
|
<relationship kind="outlet" name="siteNameTip" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="smallPlayButton" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="toolButton" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="toolTip" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="typeButton" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="typeTip" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="usernameButton" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="usernameTip" candidateClass="UIView"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPLogsViewController" superclassName="UIViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPLogsViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="action" name="close:" candidateClass="UIBarButtonItem"/>
|
||||||
|
<relationship kind="action" name="mail:" candidateClass="UIBarButtonItem"/>
|
||||||
|
<relationship kind="action" name="refresh:" candidateClass="UIBarButtonItem"/>
|
||||||
|
<relationship kind="action" name="toggleLevelControl:" candidateClass="UISegmentedControl"/>
|
||||||
|
<relationship kind="outlet" name="levelControl" candidateClass="UISegmentedControl"/>
|
||||||
|
<relationship kind="outlet" name="logView" candidateClass="UITextView"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPMainViewController" superclassName="UIViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPMainViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="action" name="action:" candidateClass="UIBarButtonItem"/>
|
||||||
|
<relationship kind="action" name="closeAlert"/>
|
||||||
|
<relationship kind="action" name="closeOutdatedAlert"/>
|
||||||
|
<relationship kind="action" name="copyContent"/>
|
||||||
|
<relationship kind="action" name="editLoginName:" candidateClass="UILongPressGestureRecognizer"/>
|
||||||
|
<relationship kind="action" name="editPassword"/>
|
||||||
|
<relationship kind="action" name="incrementPasswordCounter"/>
|
||||||
|
<relationship kind="action" name="infoOutdatedAlert"/>
|
||||||
|
<relationship kind="action" name="panHelpDown:" candidateClass="UIPanGestureRecognizer"/>
|
||||||
|
<relationship kind="action" name="panHelpUp:" candidateClass="UIPanGestureRecognizer"/>
|
||||||
|
<relationship kind="action" name="resetPasswordCounter:" candidateClass="UILongPressGestureRecognizer"/>
|
||||||
|
<relationship kind="action" name="searchOutdatedElements"/>
|
||||||
|
<relationship kind="action" name="toggleUser"/>
|
||||||
|
<relationship kind="action" name="upgradePassword"/>
|
||||||
|
<relationship kind="outlet" name="actionsTipContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="alertBody" candidateClass="UITextView"/>
|
||||||
|
<relationship kind="outlet" name="alertContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="alertTitle" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="contentContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="contentField" candidateClass="UITextField"/>
|
||||||
|
<relationship kind="outlet" name="contentTipBody" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="contentTipContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="displayContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="helpContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="helpView" candidateClass="UIWebView"/>
|
||||||
|
<relationship kind="outlet" name="loginNameContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="loginNameField" candidateClass="UITextField"/>
|
||||||
|
<relationship kind="outlet" name="loginNameTipBody" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="loginNameTipContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="outdatedAlertBack" candidateClass="UIImageView"/>
|
||||||
|
<relationship kind="outlet" name="outdatedAlertCloseButton" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="outdatedAlertContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="passwordCounter" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="passwordEdit" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="passwordIncrementer" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="passwordUpgrade" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="passwordUser" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="pullDownGesture" candidateClass="UIPanGestureRecognizer"/>
|
||||||
|
<relationship kind="outlet" name="pullDownView" candidateClass="UIImageView"/>
|
||||||
|
<relationship kind="outlet" name="pullUpGesture" candidateClass="UIPanGestureRecognizer"/>
|
||||||
|
<relationship kind="outlet" name="pullUpView" candidateClass="UIImageView"/>
|
||||||
|
<relationship kind="outlet" name="searchDelegate" candidateClass="MPElementListSearchController"/>
|
||||||
|
<relationship kind="outlet" name="searchTipContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="siteName" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="toolTipBody" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="toolTipContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="toolTipEditIcon" candidateClass="UIImageView"/>
|
||||||
|
<relationship kind="outlet" name="typeButton" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="typeTipContainer" candidateClass="UIView"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPPreferencesViewController" superclassName="UITableViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPPreferencesViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="action" name="didToggleSwitch:" candidateClass="UISwitch"/>
|
||||||
|
<relationship kind="outlet" name="avatarTemplate" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="avatarsView" candidateClass="UIScrollView"/>
|
||||||
|
<relationship kind="outlet" name="changeMPCell" candidateClass="UITableViewCell"/>
|
||||||
|
<relationship kind="outlet" name="defaultTypeLabel" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="exportCell" candidateClass="UITableViewCell"/>
|
||||||
|
<relationship kind="outlet" name="savePasswordSwitch" candidateClass="UISwitch"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPSetupViewController" superclassName="UIViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPSetupViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="action" name="close:" candidateClass="UIBarButtonItem"/>
|
||||||
|
<relationship kind="outlet" name="cloudSwitch" candidateClass="UISwitch"/>
|
||||||
|
<relationship kind="outlet" name="rememberLoginSwitch" candidateClass="UISwitch"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPTypeViewController" superclassName="UITableViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPTypeViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="outlet" name="recommendedTipContainer" candidateClass="UIView"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="MPUnlockViewController" superclassName="UIViewController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/MPUnlockViewController.h"/>
|
||||||
|
<relationships>
|
||||||
|
<relationship kind="action" name="add:" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="action" name="emergencyClose:" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="action" name="emergencyCopy:" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="action" name="facebook:" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="action" name="google:" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="action" name="mail:" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="action" name="targetedUserAction:" candidateClass="UILongPressGestureRecognizer"/>
|
||||||
|
<relationship kind="action" name="twitter:" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="avatarTemplate" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="avatarsView" candidateClass="UIScrollView"/>
|
||||||
|
<relationship kind="outlet" name="createPasswordTipView" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="emergencyActivity" candidateClass="UIActivityIndicatorView"/>
|
||||||
|
<relationship kind="outlet" name="emergencyContentTipContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="emergencyCounter" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="emergencyCounterStepper" candidateClass="UIStepper"/>
|
||||||
|
<relationship kind="outlet" name="emergencyGeneratorContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="emergencyMasterPassword" candidateClass="UITextField"/>
|
||||||
|
<relationship kind="outlet" name="emergencyName" candidateClass="UITextField"/>
|
||||||
|
<relationship kind="outlet" name="emergencyPassword" candidateClass="UIButton"/>
|
||||||
|
<relationship kind="outlet" name="emergencySite" candidateClass="UITextField"/>
|
||||||
|
<relationship kind="outlet" name="emergencyTypeControl" candidateClass="UISegmentedControl"/>
|
||||||
|
<relationship kind="outlet" name="nameLabel" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="newsView" candidateClass="UIWebView"/>
|
||||||
|
<relationship kind="outlet" name="oldNameLabel" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="passwordField" candidateClass="UITextField"/>
|
||||||
|
<relationship kind="outlet" name="passwordFieldLabel" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="passwordTipLabel" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="passwordTipView" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="passwordView" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="spinner" candidateClass="UIImageView"/>
|
||||||
|
<relationship kind="outlet" name="targetedUserActionGesture" candidateClass="UILongPressGestureRecognizer"/>
|
||||||
|
<relationship kind="outlet" name="tip" candidateClass="UILabel"/>
|
||||||
|
<relationship kind="outlet" name="uiContainer" candidateClass="UIView"/>
|
||||||
|
<relationship kind="outlet" name="wordWall" candidateClass="UIView"/>
|
||||||
|
</relationships>
|
||||||
|
</class>
|
||||||
|
<class className="PearlNavigationController" superclassName="UINavigationController">
|
||||||
|
<source key="sourceIdentifier" type="project" relativePath="./Classes/PearlNavigationController.h"/>
|
||||||
|
</class>
|
||||||
|
</classes>
|
||||||
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
||||||
<nil key="statusBar"/>
|
<nil key="statusBar"/>
|
||||||
<simulatedOrientationMetrics key="orientation"/>
|
<simulatedOrientationMetrics key="orientation"/>
|
||||||
|
Loading…
Reference in New Issue
Block a user