views:

293

answers:

2

Hi there, in my iphone app, im trying to make my uinavigationbar act as a button, i mean do something when i touch it. Not back button o any nav item, the bar itself. heres how i "categorized" it:

@implementation UINavigationBar (UINavigationBarCategory)
- (void)drawRect:(CGRect)rect {
    UIColor *color = [UIColor blackColor];
    UIImage *img    = [UIImage imageNamed: @"bar.png"];
    [img drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    self.tintColor = color;
}

The action would be navigate to some view..
Any ideas?
Thanks in advance!

A: 

Try overriding these three functions in your category: http://developer.apple.com/iphone/library/documentation/uikit/reference/UIResponder_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006783-CH4-SW13

eliego
Thanks ill give it a try and come back!
Nicolas
Ok, so im supposed to use this 3 functions: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)eventim pretty new to how overriding works, so please be nice.. Do i have to write my code inside, or do i have to do something with the params too? Thanks for the quick reply! edit: ok i give up, dont know how to add a code tag in a comment here..
Nicolas
Start by just implementing them in your category (the exact same way as you have done with drawRect:), and output some NSLog to understand how they are called. In the end you will probably only have to add code to the touchesEnded:-method, and there perform whatever action you want.
eliego
OK great! Thanks. by the way ill leave the question open so i can get back to you if i have any problem.
Nicolas
A category is not the right place to locate custom touch handling code. See my answer for more.
Brad Larson
+1  A: 

Do not use categories to override methods from a class. From the Objective-C Programming Language guide:

Although the language currently allows you to use a category to override methods the class inherits, or even methods declared in the class interface, you are strongly discouraged from using this functionality. A category is not a substitute for a subclass. There are several significant shortcomings:

  • When a category overrides an inherited method, the method in the category can, as usual, invoke the inherited implementation via a message to super. However, if a category overrides a method that already existed in the category's class, there is no way to invoke the original implementation.

  • A category cannot reliably override methods declared in another category of the same class. This issue is of particular significance since many of the Cocoa classes are implemented using categories. A framework-defined method you try to override may itself have been implemented in a category, and so which implementation takes precedence is not defined.

  • The very presence of some methods may cause behavior changes across all frameworks. For example, if you add an implementation of windowWillClose: to NSObject, this will cause all window delegates to respond to that method and may modify the behavior of all instances of NSWindow instances. This may cause mysterious changes in behavior and can lead to crashes.

Instead, you might be best served by simply creating a transparent view or button that responds to touch and placing that above the bar area for your UINavigationController. This transparent view could then catch touch events intended for the entire bar area.

However, I'd think really hard about what you're trying to achieve with this. Overriding the standard user interactions from a built-in interface element may lead to user frustration and even potential rejection by Apple.

Brad Larson
In principle you're right, but in this particular appliance I'd say a category is fine. Nicolas doesn't seem to be too experienced with Cocoa Touch, judging by the drawRect:-method there is little other functionality to mess up, and subclassing UINavigationBar is _quite_ tricky, in my experience.
eliego
Ok great! I'll see what i can do with both answers. PS. im not experienced with Cocoa Touch.. I do my best though.
Nicolas
@eliego - In this case, subclassing is not needed. He simply can put a transparent view or button over the navigation bar portion of the screen and have that handle the touches. Advocating a practice that Apple explicitly warns about is not the right way to get a new developer started on the platform. You want people to build good habits when they are first learning the environment.
Brad Larson
OK, im done with this one! Thanks Brad and eliego! I finally just added an imageView as a subview to the uinavbar, added tint and removed the category. works really good, but not touch-handling. I wont use it because i cant get to add a uibutton as a subview instead, i shows up but it wont do anything, not even highlight. thanks again!
Nicolas