Bronze challenge solution


#1

To do this challenge I reused the imagePickerPopover property that we already created in BNRDetailViewController.m. The code is pretty self explanatory. Remember to set the UIPopoverControllerDelegate in showAssetTypePicker as it won’t already be set, and do so after the initialisation. Then add code to popoverControllerDidDismissPopover: to update the button title when the popover is dismissed. One minor issue with my solution is that I don’t know how to make the popover dismiss from within the popover’s view controller itself (BNRAssetTypeViewController) i.e. when a row in the table is selected. Instead you have to tap outside to close and update.

- (IBAction)showAssetTypePicker:(id)sender
{
    
    [self.view endEditing:YES];
    
    BNRAssetTypeViewController *avc = [[BNRAssetTypeViewController alloc] init];
    avc.item = self.item;
    
    // Display in popover for ipad;
    if([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
        
        
        self.imagePickerPopover = [[UIPopoverController alloc] initWithContentViewController:avc];
        self.imagePickerPopover.delegate = self;
        [self.imagePickerPopover presentPopoverFromBarButtonItem:sender
                                        permittedArrowDirections:UIPopoverArrowDirectionAny
                                                        animated:YES];

    } else {
        [self.navigationController pushViewController:avc
                                             animated:YES];
    } 
}
- (void) popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
    NSLog(@"User dismissed popover");
    self.imagePickerPopover = nil;
    
    NSString *typelabel = [self.item.assetType valueForKey:@"label"];
    if (!typelabel) {
        typelabel = @"None";
    }
    self.assetTypeButton.title = [NSString stringWithFormat:@"Type: %@", typelabel];
    
}

#2

To dismiss the popover, I created a block called ''dismissBlock" in BNRDetailViewController.m, so that BNRAssetTypeViewController can call it after a cell is selected.


BNRDetailViewController.m
@property (strong, nonatomic) UIPopoverController *assetTypePopover;

- (IBAction)showAssetTypePicker:(id)sender
{
    [self.view endEditing:YES];

    BNRAssetTypeViewController *avc = [[BNRAssetTypeViewController alloc] init];
    avc.item = self.item;

    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
        avc.dismissBlock = ^{
            [self.assetTypePopover dismissPopoverAnimated:YES];
            self.assetTypePopover = nil;
            
            NSString *typeLabel = [self.item.assetType valueForKey:@"label"];
            self.assetTypeButton.title = [NSString stringWithFormat:@"Type: %@", typeLabel];
        };
        self.assetTypePopover = [[UIPopoverController alloc]
                                        initWithContentViewController:avc];
        self.assetTypePopover.delegate = self;
        
        [self.assetTypePopover
                presentPopoverFromBarButtonItem:sender
                       permittedArrowDirections:UIPopoverArrowDirectionAny
                                       animated:YES];
    } else {
        [self.navigationController pushViewController:avc animated:YES];
    }
}

-(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
    if (popoverController == self.imagePickerPopover) {
        self.imagePickerPopover = nil;
    } else if (popoverController == self.assetTypePopover) {
        self.assetTypePopover = nil;
    }
}


BNRAssetTypeViewController.h

@property (nonatomic, copy) void (^dismissBlock)(void);


BNRAssetTypeViewController.m

-(void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    ...
    self.item.assetType = assetType;

    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
        self.dismissBlock();
    } else {
        [self.navigationController popViewControllerAnimated:YES];
    }
}

#3

That’s a great solution but I was wondering if you shouldn’t weakify and strongify self before using it inside a block.