Resolve main thread access issues.
This commit is contained in:
		@@ -76,10 +76,7 @@
 | 
			
		||||
    NSDictionary *keyQuery = [self createKeyQueryforUser:user origin:&keyOrigin];
 | 
			
		||||
    id<MPAlgorithm> keyAlgorithm = user.algorithm;
 | 
			
		||||
    MPKey *key = [[MPKey alloc] initForFullName:user.name withKeyResolver:^NSData *(id<MPAlgorithm> algorithm) {
 | 
			
		||||
        return ![algorithm isEqual:keyAlgorithm]? nil:
 | 
			
		||||
               PearlMainQueueAwait( (id)^{
 | 
			
		||||
                   return [PearlKeyChain dataOfItemForQuery:keyQuery];
 | 
			
		||||
               } );
 | 
			
		||||
        return ![algorithm isEqual:keyAlgorithm]? nil: [PearlKeyChain dataOfItemForQuery:keyQuery];
 | 
			
		||||
    }                                 keyOrigin:keyOrigin];
 | 
			
		||||
 | 
			
		||||
    if ([key keyIDForAlgorithm:user.algorithm])
 | 
			
		||||
 
 | 
			
		||||
@@ -131,7 +131,7 @@
 | 
			
		||||
- (IBAction)valueChanged:(id)sender {
 | 
			
		||||
 | 
			
		||||
    if (sender == self.savePasswordSwitch)
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
            MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context];
 | 
			
		||||
            if ((activeUser.saveKey = self.savePasswordSwitch.on))
 | 
			
		||||
                [[MPiOSAppDelegate get] storeSavedKeyFor:activeUser];
 | 
			
		||||
@@ -139,13 +139,11 @@
 | 
			
		||||
                [[MPiOSAppDelegate get] forgetSavedKeyFor:activeUser];
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
 | 
			
		||||
            PearlMainQueue( ^{
 | 
			
		||||
            [self reload];
 | 
			
		||||
            } );
 | 
			
		||||
        }];
 | 
			
		||||
 | 
			
		||||
    if (sender == self.touchIDSwitch)
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
            MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context];
 | 
			
		||||
            if ((activeUser.touchID = self.touchIDSwitch.on))
 | 
			
		||||
                [[MPiOSAppDelegate get] storeSavedKeyFor:activeUser];
 | 
			
		||||
@@ -153,9 +151,7 @@
 | 
			
		||||
                [[MPiOSAppDelegate get] forgetSavedKeyFor:activeUser];
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
 | 
			
		||||
            PearlMainQueue( ^{
 | 
			
		||||
            [self reload];
 | 
			
		||||
            } );
 | 
			
		||||
        }];
 | 
			
		||||
 | 
			
		||||
    if (sender == self.generated1TypeControl || sender == self.generated2TypeControl || sender == self.storedTypeControl) {
 | 
			
		||||
@@ -167,42 +163,34 @@
 | 
			
		||||
            self.storedTypeControl.selectedSegmentIndex = -1;
 | 
			
		||||
 | 
			
		||||
        MPResultType defaultType = [self typeForSelectedSegment];
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
            [[MPiOSAppDelegate get] activeUserInContext:context].defaultType = defaultType;
 | 
			
		||||
            [context saveToStore];
 | 
			
		||||
 | 
			
		||||
            PearlMainQueue( ^{
 | 
			
		||||
            [self reload];
 | 
			
		||||
            } );
 | 
			
		||||
        }];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (IBAction)previousAvatar:(id)sender {
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context];
 | 
			
		||||
        activeUser.avatar = (activeUser.avatar - 1 + MPAvatarCount) % MPAvatarCount;
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
 | 
			
		||||
        NSUInteger avatar = activeUser.avatar;
 | 
			
		||||
        PearlMainQueue( ^{
 | 
			
		||||
            self.avatarImage.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)avatar )];
 | 
			
		||||
        } );
 | 
			
		||||
        self.avatarImage.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)activeUser.avatar )];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (IBAction)nextAvatar:(id)sender {
 | 
			
		||||
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
    [MPiOSAppDelegate managedObjectContextForMainThreadPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
        MPUserEntity *activeUser = [[MPiOSAppDelegate get] activeUserInContext:context];
 | 
			
		||||
        activeUser.avatar = (activeUser.avatar + 1 + MPAvatarCount) % MPAvatarCount;
 | 
			
		||||
        [context saveToStore];
 | 
			
		||||
 | 
			
		||||
        NSUInteger avatar = activeUser.avatar;
 | 
			
		||||
        PearlMainQueue( ^{
 | 
			
		||||
            self.avatarImage.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)avatar )];
 | 
			
		||||
        } );
 | 
			
		||||
        self.avatarImage.image = [UIImage imageNamed:strf( @"avatar-%lu", (unsigned long)activeUser.avatar )];
 | 
			
		||||
    }];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -149,11 +149,13 @@ typedef NS_ENUM( NSUInteger, MPActiveUserState ) {
 | 
			
		||||
            }
 | 
			
		||||
            case MPActiveUserStateLogin: {
 | 
			
		||||
                self.entryField.enabled = NO;
 | 
			
		||||
                [self selectedAvatar].spinnerActive = YES;
 | 
			
		||||
                MPAvatarCell *selectedAvatar = [self selectedAvatar];
 | 
			
		||||
                selectedAvatar.spinnerActive = YES;
 | 
			
		||||
                NSIndexPath *selectedPath = selectedAvatar? [self.avatarCollectionView indexPathForCell:selectedAvatar]: nil;
 | 
			
		||||
                NSString *masterPassword = self.entryField.text;
 | 
			
		||||
                if (![MPiOSAppDelegate managedObjectContextPerformBlock:^(NSManagedObjectContext *context) {
 | 
			
		||||
                    BOOL signedIn = NO, isNew = NO;
 | 
			
		||||
                    MPUserEntity *user = [self selectedUserInContext:context isNew:&isNew];
 | 
			
		||||
                    MPUserEntity *user = selectedPath? [self userForIndexPath:selectedPath inContext:context isNew:&isNew]: nil;
 | 
			
		||||
                    if (!isNew && user)
 | 
			
		||||
                        signedIn = [[MPiOSAppDelegate get] signInAsUser:user saveInContext:context
 | 
			
		||||
                                                    usingMasterPassword:masterPassword];
 | 
			
		||||
@@ -570,21 +572,10 @@ referenceSizeForFooterInSection:(NSInteger)section {
 | 
			
		||||
    return (MPAvatarCell *)[self.avatarCollectionView cellForItemAtIndexPath:selectedIndexPaths.firstObject];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPUserEntity *)selectedUserInContext:(NSManagedObjectContext *)context isNew:(BOOL *)isNew {
 | 
			
		||||
 | 
			
		||||
    MPAvatarCell *selectedAvatar = [self selectedAvatar];
 | 
			
		||||
    if (!selectedAvatar) {
 | 
			
		||||
        // No selected user.
 | 
			
		||||
        *isNew = NO;
 | 
			
		||||
        return nil;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return [self userForIndexPath:[self.avatarCollectionView indexPathForCell:selectedAvatar] inContext:context isNew:isNew];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
- (MPUserEntity *)userForIndexPath:(NSIndexPath *)indexPath inContext:(NSManagedObjectContext *)context isNew:(BOOL *)isNew {
 | 
			
		||||
    
 | 
			
		||||
    if ((*isNew = indexPath.item >= [self.userIDs count]))
 | 
			
		||||
    *isNew = NO;
 | 
			
		||||
    if (!indexPath || (*isNew = indexPath.item >= [self.userIDs count]))
 | 
			
		||||
        return nil;
 | 
			
		||||
 | 
			
		||||
    return [MPUserEntity existingObjectWithID:self.userIDs[indexPath.item] inContext:context];
 | 
			
		||||
@@ -756,9 +747,11 @@ referenceSizeForFooterInSection:(NSInteger)section {
 | 
			
		||||
    PearlMainQueue( ^{
 | 
			
		||||
        BOOL isNew = NO;
 | 
			
		||||
        NSManagedObjectID *selectUserID = [MPiOSAppDelegate get].activeUserOID;
 | 
			
		||||
        if (!selectUserID)
 | 
			
		||||
            selectUserID = [self selectedUserInContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]
 | 
			
		||||
        if (!selectUserID) {
 | 
			
		||||
            selectUserID = [self userForIndexPath:self.avatarCollectionView.indexPathsForSelectedItems.firstObject
 | 
			
		||||
                                        inContext:[MPiOSAppDelegate managedObjectContextForMainThreadIfReady]
 | 
			
		||||
                                            isNew:&isNew].permanentObjectID;
 | 
			
		||||
        }
 | 
			
		||||
        [self.avatarCollectionView reloadData];
 | 
			
		||||
 | 
			
		||||
        NSUInteger selectedAvatarItem = isNew? [self.userIDs count]: selectUserID? [self.userIDs indexOfObject:selectUserID]: NSNotFound;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user