Silver Challenge


#1

In my implementation, I added a navigation bar button to AssetTypePicker’s init:

[code]- (id)init
{
// Call the superclass’s designated initializer
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
UINavigationItem *n = [self navigationItem];

    [n setTitle:@"Asset Type"];
    
    // Create a new bar button item that will send
    // addNewAssetType: to AssetTypePicker
    UIBarButtonItem *bbi = [[UIBarButtonItem alloc] 
                            initWithBarButtonSystemItem:UIBarButtonSystemItemAdd 
                            target:self 
                            action:@selector(addNewAssetType:)];
    
    // Set this bar button item as the right item in the navigationItem
    [[self navigationItem] setRightBarButtonItem:bbi];
}

return self;

}
[/code]

This doesn’t seem to add the Navigation Bar Button to a UIPopover. It does wok on a regular UITableView though. Am I missing something? Any help would be much appreciated.

I added a UIPopoverController in the bronze challenge as followed (and I’m trying to get this to work with the above navigation bar button):

// CH. 16: Core Data - Bronze Challenge - Present showAssetTypePicker as Popover
// I added a bar button (instead of using a regular button) to achieve this
- (IBAction)showAssetTypePickerPad:(id)sender 
{
    if([assetTypePickerPopover isPopoverVisible]) {
        [assetTypePickerPopover dismissPopoverAnimated:YES];
        assetTypePickerPopover = nil;
        return;
    }  
    
    [[self view] endEditing:YES];
    
    AssetTypePicker *assetTypePicker = [[AssetTypePicker alloc] init];
    [assetTypePicker setItem:item];
    
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        assetTypePickerPopover = [[UIPopoverController alloc] initWithContentViewController:assetTypePicker];
        
        [assetTypePickerPopover setDelegate:self];
        
        [assetTypePickerPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
    } else {
        [[self navigationController] pushViewController:assetTypePicker animated:YES];
    } 
}

#2

I see where I missed a step. I needed to add the assetTypePicker (table view) to a UINavigationController, then add this navigation controller to the UIPopoverController (assetTypePickerPopover). Now this works when I press the bar button I created to display the AssetTypePicker as a popover, along with a right bar button to add an asset type.


#3

With this challenge I present the user with a UIAlertView, using the AlertViewStyle of UIAlertViewStylePlainTextInput available in iOS 5.

In BNRItemStore I implemented an instance method called [color=#0040BF]createAssetType:[/color]

[code]- (void)createAssetType:(NSString *)at
{
NSManagedObject *type;

type = [NSEntityDescription insertNewObjectForEntityForName:@"BNRAssetType" 
                                     inManagedObjectContext:context];

[type setValue:at forKey:@"label"];
[allAssetTypes addObject:type];

}[/code]

I then declared the AssetTypePicker as UIAlertViewDelegate, and in the implementation I added a UIBarButtonItem which would invoke a method called [color=#0040BF]addNewAssetType:[/color]

[code]- (void)addNewAssetType:(id)sender
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@“Create New Asset Type” message:nil delegate:self cancelButtonTitle:@“Cancel” otherButtonTitles:@“Done”, nil];

[alert setAlertViewStyle:UIAlertViewStylePlainTextInput];
[alert show];

}[/code]

Using the UIAlertViewDelegate method [color=#0040BF]alertView:didDismissWithButtonIndex:[/color], I then send a message to the BNRItemStore [color=#0040BF]createAssetType:[/color] method, creating the new asset, and reloading the table view data:

[code]- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0)
return;

NSString *at = [[alertView textFieldAtIndex:0] text];

[[BNRItemStore sharedStore] createAssetType:at];

[[self tableView] reloadData];

}[/code]


#4

Is that last chunk of code in BNRItemStore?

I get two errors:

“No know class method for selector ‘shardStore’”

“No visible @interface for 'BNRItemStore declares the selector ‘tableView’”


#5

The UIAlertView is brilliant!

To reply to the last person.
In AssetTypePicker.h make sure you have the protocol
In AssetTypePicker.m use the

(you called it that last chunk of code) to get the text you just input in the UIAlertView and pass it to the createAssetType method created earlier in BNRItemStore.


#6

Can you post how your new showAssetTypePicker method looks like after you’ve implemented this? Mine doesn’t seem to work when push the navigationController onto the popover.

Thanks!


#7

I also couldn’t make the navigation bar to appear in the popover.
After, couple hours I deciphered what StanleyL meant by "assetTypePicker (table view) to a UINavigationController, then add this navigation controller to the UIPopoverController (assetTypePickerPopover). "

First, the easy part.
In the AssetTypePicker.m file we change the “init” method and set navigationItem to display a button “New”:

[code]-(id) init
{
self= [super initWithStyle:UITableViewStyleGrouped];

if (self) {
    UINavigationItem *n = [self navigationItem];
    [n setTitle:@"Asset Type"];
    
UIBarButtonItem *newItem = [[UIBarButtonItem alloc]
                             initWithTitle:@"New"
                            style:UIBarButtonSystemItemAdd
                            target:self
                            action:@selector(addNewAsset:)];

[[self navigationItem] setRightBarButtonItem:newItem];
}

return self;

} [/code]

Now the difficult part.
We make changes in the DetailViewController.m file in the method "showAssetTypePicker: " were we initialize our popover AssetTypePicker.
Before, we initialized AssetTypePicker and then initialized the popover to have the AssetTypePicker to be inside. But AssetTypePicker is a simple a UITableViewController,

Now, because we want to play around with the navigation bar we need to initialize a random UINavigationController object right in the "ShowAssetTypePicker: " method, right after we’ve initialized the AssetTypePicker.
By “Control Clicking” the “UINavigationController” and revealing its declaration we found their an initializer that specify with what controller the UINavigationController should be. The method is:
"initWithContentViewController:"
We write:

Now we have a UINavigationController with the AssetTypePicker inside.
We change our previous initialization of the popover so that it will be “initWithContentViewController:naviagationItem” :

imagePickerPopover = [[UIPopoverController alloc] initWithContentViewController:navigationController];

The “showAssetTypePicker:” now looks (i used our old “imagePickerPopover” instance variable):

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

//...if a popover already visible - close it:
if([imagePickerPopover isPopoverVisible]) {
    [imagePickerPopover dismissPopoverAnimated:YES];
    imagePickerPopover = nil;
    return;
}

//...initializing the controller that should appear inside a popover:
AssetTypePicker *assetTypePicker = [[AssetTypePicker alloc] init];
[assetTypePicker setItem:item];

[imagePickerPopover setDelegate:self];

//16...silver challenge. Putting a navigation bar on top of the AssetTypePicker:
UINavigationController *navigationController=[[UINavigationController alloc] initWithRootViewController:assetTypePicker];
                                              
//...set our popover to display navigationController:
imagePickerPopover = [[UIPopoverController alloc] initWithContentViewController:navigationController];

//...create a rectangle from which the popover should appear:
CGRect rect = [[self view] convertRect:[sender bounds] fromView:sender];
[imagePickerPopover presentPopoverFromRect:rect
                              inView:[self view]
            permittedArrowDirections:UIPopoverArrowDirectionAny
                            animated:YES];

}[/code]

Run the app and observe that mother f* bar at the top.
http://www.ZhenyaVlasov.com