I'm having a strange issue where a custom control I've built for the iPhone works perfectly when building in debug mode but only works partially when built in release mode.
The main wrapper view is a subclass of UIView and it contains a row of "buttons" that are added as subviews. The custom button class extends UIImageView and is overriding the touch methods with the following signatures:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
When building debug code, all 4 of these functions are called at the times you would expect, with a release build, nothing happens. I have logging in each of them and I'm not getting any log messages (other logging is working).
Another interesting thing, I have the touchesBegan/Moved/Ended methods overridden in the wrapper view class and they are working fine. I've tried commenting out those methods in the wrapper class to see if it had an effect on the buttons but it did not.
I've also tried changing the UIImageView class to be a subclass of UIButton instead but am having the same issue there, including any events like touchUpInside. They work in debug, but not release.
I've tried researching this issue as well as general event handling and have come up empty handed. Any ideas where to look next?
I finally figured out the issue - the wrapper for the "button" items had a height of 0. In debug mode, the app figured out that the buttons were being touched even though they weren't inside the hit area of their parent view (clipsToBounds was defaulted to NO so the button items were still perfectly visible), in release mode, not so much.
Hopefully this can help save some people the head scratching and debugging time that I had to go through :) I've also posted this to a bug at Apple so hopefully it will be fixed someday.
Related
When the app is launched, I want to freeze UI for a second or so to get a precondition service (for example - location service) initialized. Is there a way to do that?
Just place a transparent UIView on top of the entire screen and have it intercept all touch events.
To intercept touch events, simply subclass a UIView and override
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event;
Usually inside that method you'd call super on it, but in this case you would just return YES:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
return YES;
}
If you'd like to be really fancy you can add a synthesized property to the UIView subclass called shouldInterceptTouches and do something like this:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
return shouldInterceptTouches ? YES : [super pointInside:point withEvent:event];
}
Also remember to make sure that your transparent view is above the other views.
Side-note: Apple's Human Interface Guidelines don't like it when you do stuff like that. A user will be confused and disappointed if your app is not responsive and it may cause them to quit the app if they think it's frozen. You're better off displaying some sort of UIActivityIndicatorView and disabling only the buttons absolutely necessary. Apple likes it when you do stuff like that in the background and allow the user to do other things, just in case it takes a while or fails.
You could use a Modal View or disable all components until the location service has finished.
This is the responsibility of the application not the OS or the frameworks.
I'm building an iPhone app on top of the OpenGL template for the iPhone. I was about to add user interaction to the app when I noticed that it won't respond to touches in a few of my classes.
Currently, the GameAppDelegate calls my EAGLView class' startAnimation method, which eventually calls my ES1Renderer class' render method, which then finally calls my Scene render method. I know it's a bit of a mess at this point, but I'll clean it up eventually.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event is only called and checked for in my EAGLView class. I don't know what I'm missing in the other classes (most importantly my Scene class) that will automatically check to see if I have that method and implement it.
Judging just from the naming scheme, it sounds like Scene is not a UIView. The touch event method is called on whatever UIView is touched -- in this case, your EAGLView. If you'd like the Scene class to handle it, you can just call the method directly:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[myScene touchesBegan:touches withEvent:event];
}
For some reason my touchesBegan method doesn't seem to be responding correctly. If I touch the screen with two fingers, then lift one up and put it down again, touchesBegan gets called correctly. If I touch the screen with one finger, then add a second finger, touchesBegan does not get called like it should. Is there some flag that I need to check? Below is a sample that illustrates my problem:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"touch");
}
Any ideas what's going on? I'm testing on an iPad with iOS 4.2 if it matters.
Yes, you need to set the multipleTouchEnabled property on your view.
When set to NO, the receiver receives
only the first touch event in a
multi-touch sequence. The default
value of this property is NO.
i'm trying to make a connect four iphone app. I have made my own custom UIView class, which is where the game is played. However, I am trying to use the touchesMoved, touchesEnded, etc. methods to retrieve data based on where the user clicked (so i know which column they are trying to put a piece into). How can i get this information from the viewController class to my UIview class?
I would just use - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event and potentially override - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event to ignore touches in views that I may have overlaid. It does depend on your view hierarchy really.
I'm working on an iPhone app which involves typing stuff into a UITextView, which adds content to a UITableView. The problem is, I need to be able to close the keyboard when the user's done with it, and the only area that is really visible other than the keyboard and UITextView at this point is the UITableView. I'm having trouble implementing a touch event on the UITableView (as in, touching the UITableView anywhere, not just didSelectRowAtIndexPath:). Here's the code I'm using in the view controller, which doesn't do anything at all:
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[textView resignFirstResponder];
}
Any suggestions?
That looks like correct code to me. Put a breakpoint in to make sure it's being called.