Cocoa NSView: overlapping view's doesn't block controls underneath - objective-c

I have 2 views 1 view has NSTextFields (viewA) the other one (viewB) just overlaps viewA
but i can still on the textfields even though viewB completly overlaps the textfields.
is there an easy way to block this ?

Mouse events go to whoever will accept them, so put
- (void)mouseDown:(NSEvent *)theEvent { }
in View B.

Related

NSView Absorb Clicks?

I have my standard app setup, window with lots of views. From time to time I place an NSView over the top of everything, black with some transparency, to act an a dimmer/overlay.
I need this top overlay view to absorb all clicks so that any views underneath it can't be interacted with. E.g. an NSButton under this NSView won't be clickable.
How can I do this?
I have seen -(NSView *)hitTest:(NSPoint)aPoint but I don't want to put this on every single subview with a rule to block clicks while the overlay view is present.
Override the NSView with an empty mouseDown: and the views underneath will not receive any mouse events.

scrollview, buttons events exchange

I have a scrollview where I added several buttons (dynamically, programmatically). Hence my view is totally covered with buttons. Also there are some labels
However, I observed that the uiscrollview is not scrolling when the drag starts on the button. All labels work fine. But I want this scroll to happen i.e. when drag event occurs in the uibutton, I want it to send this event to its superview (scrollview).
Please note, according to my search, subclassing the scrollview and overrriding the content touches event, or add touch began actions to uibuttons are not helpful.
How do one in general work with this event passing things when objects are added dynamically?
You have to subclass the UIScrollView, there's no other proper way, but you do not need to mess with the touch events. All you have to do is override this method
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
return YES;
}
And set the canCancelContentTouches property of the UIScrollView to YES.

IOS Accessing one view from another view

Basically I have a view controller having two subviews. I want these views to be connected. A touch event should trigger an event from another view and vice versa. I have thought about two solutions.
1-) Accessing views through their view controllers
2-) Each view has a pointer to another view
I am a newbie on IOS and as far I read from other problems it is mentioned that accessing view controller from a view is not suggested. So, what do you guys suggest me to do?
Edit:
I didn't make much progress on coding but my first view is:
#interface PaintView : UIView
-(id)initWithFrame:(CGRect)frame andController:(ViewController*)ctrl;
and i will control the touch event and access my viewcontroller:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//[self.controller somethingThatAccessToOtherView]
}
and second view will be very similar to that one.
Why dont you use the delegate pattern!
For the two views communicate with each other ..
Its essentially similar to " Each view has a pointer to another view" but in a much more flexible manner
here is a so thread on it and
If you want the simplest, dirtiest, and non recommended way of proceeding. Tag your two views with some sort of unique tag (use say, -20 and -21, or something. So in the view controller where you create the views you do the following.
[v1 setTag:-20];
[v2 setTag:-21];
Then you can do from in say, v2, the following.
[self.superview viewWithTag:-20];
to get a reference to v1. However, this assumes the same superview, and is not a nice way of doing things unless you are sure that the view heirachy will not change (I'm talking, it's a widget you made that no one else is going to touch and you've documented it well anyway).
A better way would be to use a delegate pattern. The ViewController is the delegate of each of the subviews. On touch, the subviews call some method like
[delegate iwastouched:self];
and the delegate has a method like
-(void) iwastouched:(UIView *) someview {
if(someview == v1){
//view 1 was touched, do something to view two
}
if(someview == v2){
//view 2 was touched, do something to view one
}
}
Another bad way of doing it would be to use notifications. Hell, there are about as many ways to do this as you could like. Some are just not as nice.
Instead of doing this, in the subclass of UIViewController, you should have two members. These member will represent each of the subview.
Now, inside the subclass of UIViewController, add the methods of touch which are of your interest. Inside this methods, identify the view on which any touch event is generated.
Depending on it, pass the event to other view.
You should not have UIViewController as a iVar of your UIView subclass.

Detecting all touches in an app

In an iPad app, wherever a user is touching the screen I want to display an image, highlighting the points they are touching. The app contains a number of nested views, all of which should receive touches and behave normally.
Seems simple, but I've failed to find a good way to do it. Using the touches began: with event and related functions on the root view controller does not work because if a subview is touched the events are not fired. I've also created a 'dummy' gesture recognizer which just passes touch events to another class which draws images. That works great-ish and buttons work, but breaks UIScrollViews and I'm guessing other subviews with gesture reconizers.
Is there nowhere you can just access all touch events without affecting where those touches are headed?
thanks.
Your dummy gesture recognizer should be ok. Just watch out for setting states. possible -> began -> ...
Basically your gesture recognizer is forwarding all touches so it can be in began or possible state all the time while any touch exists.
To get rid of problems with other gesture recognizers return YES in this delegate method.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
Other option is to subclass main UIWindow in your app and override this method
- (void)sendEvent:(UIEvent *)event
Here you should have access to all events. It's quite easy to filter them.
You can apply a UITapGestureRecognizer to the entire view and set the cancelsTouchesInView property to NO. This will allow you to be notified of all taps on the view and its subviews without intercepting all of the touch events.
Additionally, you can implement the -gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: delegate method to keep this gesture recognizer from stomping on the ones used by views like UIScrollView.
you can try overriding hitTest:withEvent:
-(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
This maybe what you are looking for.

UIResponder chain question

Im not too informed on the nitty gritty of modifying the responder chain, so if this is stupid pls dont bash me ;)
basically i have 2 view stacks(blue) as a subview of a parent view(red)
they are both occupying the full frame of parent at one point in time, so obviously only the one on top is getting touch events, which travel upstream to the parent view(red) and on to window.
During some cases i want the touch input to be picked up by the eligible child view of 'other' view stack. That is, the view that woud be receiving these inputs if the current topmost view had userinteractionenabled set to no.
Setting userinteractionenabled works but i feel like its a dirty hack. The gist is this topmot view is mostly transparent and i want the events when touched in the specified region to end up on the other stack.
here is a picture to help visually explain, and keep in mind both blue views are 100% of parent.
http://c.crap.ps/35a5
You can override hitTest:withEvent: in each of the views to control who gets to "consume" the touch.
In your example I am assuming that the greenish areas are subviews that you want to consume the touch events. If so, then try this for the hitTest method:
-(UIView*) hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *hitView = [super hitTest:point withEvent:event];
return (hitView == self) ? nil : hitView;
}
This method checks if the touch hits any of the subviews. If it does then it lets that subview consume the touch, otherwise it lets the touch continue through the hierarchy.