UIImageView subclass not passing touches to controller subviews - objective-c

When I add a UIImageView subclass (fullscreen) behind a couple of UIButton subclass instances, those buttons stop receiving the touches and don't function anymore. Nothing I have tried has worked to restore their connectivity to user touches.
I have tried:
a) Using a UIImageView subclass for the front view (that receives the touches) and making sure setUserInteractionEnabled is YES. Result: UIButtons are not responding when the UIView is present.
b) Explicitly passing the touches from the front view to the view controller in hopes that it will do the right thing. Result: UIButtons are not responding to the touches.
c) Calling the touchesBegan, touchesMoved and touchesEnded methods directly on the button I want to interact with when any touch on the front UIView is received. Result: Strikingly, the buttons don't respond even when I am cramming the touch events down their throat.
d) Passing the touches from the front view to the UIViewController, and iterating over all subviews handing out the touches manually. I included a touchesBegan method showing how I tried to do this. When executed the loop is infinite, it never progresses past the first view (is of type FrameUIView).
I know this problem is likely the result of my lack of understanding of proper view hierarchy or the responder chain.
if I comment the last view created after the button, then the buttons work fine. Is there something special about UIButtons in this respect?
Here is the code.
I have a UIViewController subclass, in it:
- (void)loadView {
mainAppView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.view = mainAppView;
frameImageView = [[FrameUIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
frameImageView.image = [UIImage imageNamed:[[[ThemeController sharedInstance] currentTheme] frameImageFilename]];
[frameImageView setUserInteractionEnabled:YES];
[mainAppView addSubview:frameImageView];
zoomInButton = [[CustomUIButton alloc] initWithFrame:CGRectMake(controlsOriginX + zoomWidth + lightWidth, controlsOriginY, zoomWidth, controlsHeight)];
[zoomInButton setTitle:#"+" forState:UIControlStateNormal];
[[zoomInButton titleLabel] setFont:[UIFont systemFontOfSize:28]];
[zoomInButton addTarget:self action:#selector(doMyAction) forControlEvents:UIControlEventTouchDown];
[zoomInButton addTarget:self action:#selector(cancelMyAction) forControlEvents:UIControlEventTouchUpInside];
[mainAppView addSubview:zoomInButton];
FrameFrontUIView *frameFrontImageView = [[FrameFrontUIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
frameFrontImageView.image = [UIImage imageNamed:[[[ThemeController sharedInstance] currentTheme] frameFrontImageFilename]];
[frameFrontImageView setUserInteractionEnabled:YES];
[mainAppView addSubview:frameFrontImageView];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UIView *view in self.view.subviews) {
NSLog(#"view is a %#", [view description]);
[view touchesBegan:touches withEvent:event];
}
}
Anyone with a tip on how to do this wins the internets and a cookie. Also accepting revolvers for russian roulette mayhem. Thank you.

Have you tried using the buttons without the image view behind them? Subclassing UIButton is not advisable. The way to instantiate UIButtons is with factory methods:
UIButton* myButton = [UIButton buttonWithType:UIButtonTypeCustom];
So my guess is that the CustomUIButton instances you have created are not properly set up.

This question is old, but I just ran into the same problem.
The solution I used is to create a container UIView, then add the UIImageView as a subview, then add the buttons, text boxes, etc. over that. Seems to work well.
I don't really understand why this is an issue with using a UIImageView as the superview for buttons.

Related

Can't programmatically move label in viewDidLoad

I'm trying to move a uiLabel down a drop if it's an iPhone 5 (4" display). But it's not working when the code is in viewDidLoad. If I call the code from clicking a uiButton, it works. Here's the code:
-(void) viewDidLoad {
if(CGSizeEqualToSize([[UIScreen mainScreen] preferredMode].size,CGSizeMake(640, 1136))) {
CGRect frame = [self.timeOnCurrentQuestion frame];
frame.origin.y += 40; // change the location
[self.timeOnCurrentQuestion setFrame:frame];
nslog(#"This DOES get logged");
}
}
Jonah, have you tried your code in viewWillAppear method? Possibly, it'll sort-out your issue.
Maybe that are something you need to beware of.
- (void)viewDidLoad
It is a method that when the controller juz created its view.
for example:
maybe in your init method, you call something like:
[self.view setBackground:[UIColor redColor]];
self.timeOnCurrentQuestion = [[UIView alloc] initWithFrame:kFrame];
In this case the work flow will be like this:
[self.view setBackground:[UIColor redColor]];
[self viewDidload];
self.timeOnCurrentQuestion = [[UIView alloc] initWithFrame:kFrame];
Th reason for this work flow is because the self.view is called, then its view is needed before the normal view cycle, so , in this case, self.timeOnCurrentQuestion is still nil in the viewDidload method.
I don't know if my practice is the best or not.
I always init the subView in the controller's init method.
and do the [self.view addSubview:_subview] (//or everything method call that require the self.view) in [self viewDidload];
viewDidAppear worked for me. The life cycle seems to be
LoadView()
viewDidLoad()
viewWillAppear()
viewDidAppear()

UITextView not becoming first responder

I have a UIView that contains a UITextView. The UIView is initiated inside a UIViewController.
But when I touch the UITextView box, nothing happens. Neither the keyboard appears nor delegate methods respond to interaction.
Code:
noteText = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, 700, 240)];
noteText.layer.borderColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.2].CGColor;
noteText.layer.borderWidth = 2;
[noteText setEditable:YES];
noteText.userInteractionEnabled = YES;
noteText.returnKeyType = UIReturnKeyDone;
noteText.font = [UIFont fontWithName:#"Calibri" size:16];
noteText.textColor = [UIColor blackColor];
[self addSubview:noteText];
Update 1
I removed all other views from the UIViewController, and only put a UITextView in the UIViewController and still not reacting. Neither cursor or keyboard appear.
noteText = [[UITextView alloc]initWithFrame:CGRectMake(0, 0, 700, 240)];
noteText.layer.borderColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.2].CGColor;
noteText.layer.borderWidth = 2;
[noteText setEditable:YES];
noteText.userInteractionEnabled = YES;
noteText.returnKeyType = UIReturnKeyDone;
noteText.font = [UIFont fontWithName:#"Calibri" size:16];
noteText.textColor = [UIColor blackColor];
[self addSubview:noteText];
// Two suggestions
self.userInteractionEnabled = YES; // superview may blocks touches
self.clipsToBounds = YES; // superview may clips your textfield, you will see it
I found the error.
In one class I categorize the UITextView instead of subclass and set canBecomeFirstResponder to NO.
try this:
in your .h file conform the delegate UITextViewDelegate
:<UITextViewDelegate>
in your .m file:
noteText.delegate = self;
And delegate methods:
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView{
[textView becomeFirstResponder];
return YES;
}
- (BOOL)textViewShouldEndEditing:(UITextView *)textView{
//resign for exapmple
return YES;
}
Hope this help!
I know it's late, but maybe for someone it'll be helpful. I had the same problem, and it disappeared after I used
[self setSelectable:true];
in my UITextView subclass.
Check this things:
add your viewcontroller on the right UIWindow.
set window makeKeyAndVisible and add rootViewController to window at this method:
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
I think here is something wrong in xib file or at appdelegate.
Try overriding - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { inside the UIView to see if it's receiving touches
Just in case, try setting userInteractionEnabled = YES; for your UIView object. If it's somehow set as NO it will trickle down to all of its subviews
Maybe you have some mistake in your overriden -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event method? Maybe you do resignFirstResponder there or put some view above all?
Whenever something like this happens check the following items,
Make sure that the Text view is properly retained and released only in dealloc.(If you are not using ARC)
Check the frame of both Text view and it's parent views. Make sure that the subview is fitting exactly inside the parent view. Also make sure that this is the case with all the superviews of text view.
Check whether the delegate is set properly.
If all these are done, try adding a button on top of text view and check if it's target selector is getting called. If yes, the issue is with text view delegate or release statement. Otherwise the issue is with frame setting of Text view or it's superviews.

Multiple Views in Xcode 4.2

I'm having a lot of trouble finding a tutorial for implementing multiple views in Xcode 4.2 without storyboard, this is for a class so I can't use storyboard yet. I'm just trying to have a 2nd view with a UIPicker come up when a button is clicked in the main view, I just can't find one for this version of Xcode and it's different enough from the older versions to confuse me.
Any help appreciated if someone can give me a quick description of what I need to do this or a newer tutorial I'd appreciate it :)
I think you should read the UIView Programming Guide to get a good handle on how UIViews work exactly. I find nibs/storyboard are really great at confusing new iOS developers.
In essence, a UIViewController has 1 view which you set in the viewDidLoad or loadView method by using the [self setView:someUIView]. You add more stuff to the screen by adding UIViews as a subview of the viewcontroller's "Main" view. For example
-(void)loadView {
// Create a view for you view controller
UIView *mainView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self setView:mainView];
// Now we have a view taking up the whole screen and we can add stuff to it
// Let's try a button, a UIButton is a subview of UIView
UIButton *newButton = [[UIButton buttonWithType:UIButtonTypeRoundedRect];
// We need to set a frame for any view we add so that we specify where it should
// be located and how big it should be!
[newButton setFrame:CGRectMake(x,y,width,height)];
// Now let's add it to our view controller's view
[self.view addSubview:newButton];
// You can do the same with any UIView subclasses you make!
MyView *myView = [[MyView alloc] init];
[myView setFrame:CGRectMake(x,y,width,height)];
[self.view addSubview:myView];
}
Now here we have our viewController who'se view is just a plain UIView which in turn has 2 subviews; newButton and myView. Since we created the MyView class, maybe it contains subviews as well! Let's take a look at what a UIView subclass could look like:
// Here is the init method for our UIView subclass
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Let's add a button to our view
UIButton *newButton2 = [[UIButton buttonWithType:UIButtonTypeRoundedRect];
// Of course, the frame is in reference to this view
[newButton2 setFrame:CGRectMake(x,y,width,height)];
// We add just using self NOT self.view because here, we are the view!
[self addSubview:newButton2];
}
return self;
}
So in this example we would have a view controller who'se view now contains 2 button! But the view structure is a tree:
mainView
/ \
newButton myView
\
newButton2
Let me know if you have any other questions!
Matt

UIWebview scrollsToTop not working when a UIScrollview is present as subview

I'm having an issue with setScrollsToTop: on UIWebView. the webview is a subview of the root view controller and on viewDidLoad I set:
[self.webView.scrollView setScrollsToTop:YES];
However when I then tap the status bar the webview won't scroll to the top. On another modal tableViewController inside the app it works fine, without even setting setScrollsToTop:YES. This is the code in applicationDidFinishLaunching inside the app delegate:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.f = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
self.window.rootViewController = self.f;
[self.window makeKeyAndVisible];
return YES;
How can I make it work?
EDIT: It seems like a UIScrollview that is in the same view is causing the problem. How can I make it work with the UIScrollView?
Try setting setScrollsToTop:NO on the UIScrollView.
According to the docs on setScrollsToTop: in UIScrollView,
This gesture works on a single visible scroll view; if there are
multiple scroll views (for example, a date picker) with this property
set, or if the delegate returns NO in scrollViewShouldScrollToTop:,
UIScrollView ignores the request.
use the answer here: UIScrollView + UIWebView = NO scrollsToTop
worked for me like a charm.
i had a UIScrollView with a UIWebView embedded.
Maybe those code will solve you problem if I get the problem.
self.automaticallyAdjustsScrollViewInsets = NO;
CGSize containerSize = self.view.frame.size;
self.webView.frame = CGRectMake(0, 64, containerSize.wdith, containerSize.height - 65);
Sometime the self.automaticallyAdjestsScrollViewInsets is not wokring as usual. So, just turn off it.

UIView transition and animation

I understand modal views cover the entire screen. But I really want a view that covers only half the screen just like the keyboard. So, please tell me why this doesn't work
MyController *controller = [[MyController alloc] initWithNibName:#"MyView" bundle:nil];
CGRect frame = CGRectMake(0,44,768,264);
[controller view].frame = frame;
contoller.delegate = self;
[[self view] addSubView:[controller view]];
[controller release];
I am trying to add a sub view to my current view and make it appear where the keyboard appears.
It throws a BAD ACCESS exception
In my code (above), I was using a custom UIViewController with it's own view [set to UIView on IB]. I couldn't get it to work by setting frame for the view controller's view.
So I added a custom UIView without a Nib file with all the controls (buttons, textfields) added on initWithFrame.
MyCustomView = [[MyCustomView] alloc] initWithFrame:frame delegate:self];
[self.view addSubView:MyCustomView];
Thanks for your comment, Jacob.