Bugs, Buttons, and Button Colour


Well that was a marathon session on the challenge.

Here’s my code. This is the only way I could get it to work:


// ItemDetailViewController.h
// Homepwner
// Created by Steven Britton on 10-09-19.
// Copyright 2010 MyCompanyName. All rights reserved.

#import <UIKit/UIKit.h>

@class Possession;
@interface ItemDetailViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIPopoverControllerDelegate> {

IBOutlet UITextField *nameField;
IBOutlet UITextField *serialNumberField;
IBOutlet UITextField *valueField;
IBOutlet UILabel *dateLabel;

IBOutlet UIImageView *imageView;
UIPopoverController *popOver;

Possession *editingPossession;


@property (nonatomic, assign) Possession *editingPossession;



Code snippets from ItemDetailViewController.m

- (void)deleteButtonPressed:(id)sender
	NSString *oldKey = [editingPossession imageKey];
	if (oldKey) {
		// Delete the old image
		[[ImageCache sharedImageCache] deleteImageForKey:oldKey];
	[editingPossession setImageKey:nil];
	[imageView setImage:nil];
	[self setBarButtonItemCamera:self];

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
	// The variable pointing to the instance we're editing is called "editingPossession", so
	// we are going to work with that.  First, we want to check to see if there's already
	// an image there.
	NSString *oldKey = [editingPossession imageKey];	// Pull it out into a local variable
														// so we don't mess up the original until we're ready to.

	if (oldKey) {										// we execute the code inside this if statement if oldKey != nil
		// Delete the old image
		[[ImageCache sharedImageCache] deleteImageForKey:oldKey];

	// Get picked image from info dictionary
	UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];

	// Create a CFUUID object - it knows how to create unique identifies
	CFUUIDRef newUniqueID = CFUUIDCreate(kCFAllocatorDefault);
	// Create a string from unique identifier by typecasting the variable
	CFStringRef newUniqueIDString = CFUUIDCreateString (kCFAllocatorDefault, newUniqueID);
	// Use that unique ID to set our possessions imageKey
	[editingPossession setImageKey:(NSString *)newUniqueIDString];  // (NSString *) before newUniqueIDString is the point
																	// at which the typecasting occurs.

	// Above, we used "CFUUIDCreate" functions to make objects, we need to release them now.
	// Store image in the ImageCache with this key
	[[ImageCache sharedImageCache] setImage:image
									 forKey:[editingPossession imageKey]];
	// Put that image onto the screen in our image view
	[imageView setImage:image];
	// Take image picker off the screen - 
	// You must call this dismiss method
	[popOver dismissPopoverAnimated:YES];
	[self setBarButtonItemDelete:self];

- (void)viewWillAppear:(BOOL)animated
	[super viewWillAppear];
	[nameField setText:[editingPossession possessionName]];
	[serialNumberField setText:[editingPossession serialNumber]];
	[valueField setText:[NSString stringWithFormat:@"%d",
						 [editingPossession valueInDollars]]];
	// Create a NSDateFormatter that will turn a date into a simple date string
	NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
	[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
	[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
	// Use filtered NSDate object to set dateLabel contents
	[dateLabel setText: 
		[dateFormatter stringFromDate:[editingPossession dateCreated]]];
	[dateFormatter release];

	// Change the navigation item to display name of possession
	[[self navigationItem] setTitle:[editingPossession possessionName]];
	NSString *imageKey = [editingPossession imageKey];
	if (imageKey) {
		// Set the bar button item to the trash can
		[self setBarButtonItemDelete:self];
		// Get the image key from the image cache
		UIImage *imageToDisplay = [[ImageCache sharedImageCache] imageForKey];
		// use that image to put on the screen in imageView
		[imageView setImage:imageToDisplay];
	} else {
		// Set the bar button item to the camera
		[self setBarButtonItemCamera:self];
		// Clear the imageView, as the current possession currently has no image.
		[imageView setImage:nil];

- (void)setBarButtonItemCamera:(id)sender
	UIBarButtonItem *cameraBarButtonItem = [[UIBarButtonItem alloc]
	[[self navigationItem] setRightBarButtonItem:cameraBarButtonItem];
	[cameraBarButtonItem release];

- (void)setBarButtonItemDelete:(id)sender
	UIBarButtonItem *deleteBarButtonItem = [[UIBarButtonItem alloc]
											initWithTitle:@"Delete Photo" style:UIBarButtonItemStylePlain
	[[self navigationItem] setRightBarButtonItem:deleteBarButtonItem];
	[deleteBarButtonItem release];

The button is designed to toggle between the camera icon and the delete button, much like another user did on here, however in my implementation I created two methods (to make the code more efficient - at least that was my intent) however I kept getting “setBarButtonItemDelete” and “setBarButtonItemCamera” undeclared errors when I attempted to build.

My declarations in the .h file were present, and my calling of the methods were the same

// .h declaration example

// .m implementation example
[setBarButtonItemCamera];   // Would kick an "undeclared" error
[setBarButtonItemCamera:]; // Would kick a "expected identifier after : token (or something)

So I clearly am missing something regarding calling methods and messaging. (??)

Other question:

Is there a way to programatically (or otherwise) change the background colour of the delete button to, say, red, when it’s implemented on the navigation bar?

Other question: why does my code work with deleteButtonPressed being undeclared in the .h file?


There isn’t a receiver for this message.

[self setBarButtonItemCamera];