How to define a tappable area defined by coordinates - objective-c

I am writing a small iPad application that draws a shape from a list of coordinates. I would like to tap anywhere inside the shape and have some action occur (i.e. NSLog proving it worked).
Does anyone know how to create a tappable area that is defined by a list of coordinates?
The shape is being drawn on top of a MKMapView.

My approach would be:
Have the points that demark the shape live within a subclass of UIView. Override pointInside:withEvent: for that class. Then look at How can I determine whether a 2D Point is within a Polygon? and use your new knowledge to implement pointInside:withEvent:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
//Left as homework
}
You can use a regular tap gesture recognizer with this :)

Only instances of UIView are tappable, and their area is defined by their rectangular property frame. In principle it would be possible (for very simple and specific shapes) to approximate the area defined by coordinates by multiple UIViews, but this is probably not what you want.

Related

How to create a custom NSSlider with a transparent middle bar and custom knob size

I've searched around for some code on NSSliderCell but I can't find a way to do what I'm looking for.
I'd like to create something like this (where the white line is the slider knob, 1 pixel width):
I'm going to use this for the time bar of a music track, so it's going to move every second (that's why I want to use a NSSlider to make things easy).
What do I need to do to make a slider, with a transparent middle bar, similar to the image above?
PS: It's not going to be touchable, it's just for display.
You can just override drawRect:, as when subclassing NSView, except in your implementation, use [self doubleValue] to determine where to draw the line. However, I don't see the point of subclassing NSSlider in this case. A custom NSView could have a property that determines where to draw the line, and then other code could set that property or bind to it.
That looks like a vertical split view to me with a 1 pixel wide divider. You might try that. There's a method to set the position of the divider so it would be easy to move as you need. And you can make the divider 1 pixel by creating a subclass of NSSplitview and overriding the dividerThickness method to return 1. Then you just set the background of the 2 subviews to black and there you go. It's easy to try so maybe it will work for you. Good luck.
I finally got it:
I created a NSSliderCell subclass with a property #property float x;
I overrode the drawKnob method and inside it I wrote:
-(void)drawKnob:(NSRect)knobRect{ self.x = knobRect.origin.x; }
I dragged a NSSlider into my window (made it small, changed it's width to the window's width) and changed it's cell class to the one I created;
And then when the music is playing, every time a second goes by I do:
[_timeBarSlider setMinValue:0];
[_timeBarSlider setMaxValue:myTrack.duration];
[_timeBarSlider setDoubleValue:myPlayer.currentPosition];
[[_timeBarImageView animator] setFrame:NSMakeRect(_timeBarSliderCell.x, yourYCoordinate, yourWidth, yourHeight)];
_timerBarSlider is the NSSlider I have in IB / _timerBarImageView is the image view that contains the vertical image line / _timerBarSlderCell is the NSSlider's cell (subclassed)
PS: the NSSlider is behind every object in that window, so that the user can't see it. You can't setHidden:YES on it because the drawKnob method will not be called.

how to find a object in rect or at point

On a NSView there are many other NSViews and some of them are moving with keyboard scroll keys. when moving object come on top of any static one i want to get which object sits under moving one. with mouse this is easy however without mouse i couldn't find a way to achieve this.
You'll need to loop through all of the views you want to test, get each view's frame, convert that rectangle to the relevant view's coordinate system (search for “convertRect:” in the NSView docs), and then use the geometry functions to test whether the moving view's converted frame intersects the static view's frame.
This might help you
-(void)handleTap:(UIGestureRecognizer *)gesture
{
CGPoint tappedPoint = [gesture locationInView:self.view];
NSLog("You tapped in on screen point : %#",tappedPoint);
}
Using this tappedPoint we can check that in which view's rect these points are present.
Important We have to add tap gesture in our view to use this function.

CGRectContainsPoint checking a view within a subview?

I am trying to check for a collision of an UIView that is in the main view, with a UILabel that is a subview of another view in the main view.
When I use CGRectContainsPoint, it does not return true. When I check the UILabel's frame, it returns values relative to the subview it's in, not it's absolute position. I figured this might be the problem.
If so, how do I specify that I want UILabel's absolute values for the frame?
You can convert coordinates between different coordinate systems using the NSView methods:
- convertRect:(NSRect) fromView:(NSView)
- convertRect:(NSRect) toView:(NSView)
If the second argument is nil, the coordinates are converted from/to window base coordinates. Similar methods exist for NSPoint and NSSize variables. One solution would be to convert all rectangles and points to window base coordinates and check for collision in those coordinates.

iOS: Non-square hit areas for buttons

I need to make some triangular buttons that overlap each other.
While UIButtons can take transparent images as backgrounds, and UIControls can have custom views, the hit area of these is always square. How can I create a triangular hitarea for my buttons?
I come from a FLash background so I would normally create a hitarea for my view, but I don't believe I can do this in Cocoa.
Any tips?
You can achieve this by subclassing UIButton and providing your own:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
// return YES if point is inside the receiver’s bounds; otherwise, NO.
}
Apple's UIView Documentation provides the details, such as confirming that point is already in the receiver's coordinate system.

CGContext is being covered by a UIView

I'm not that great with Core Graphics, but I am drawing text on the screen to my CGContext. I am doing this immediately after I add a standard, opaque UIView to my user interface.
Does anyone know why the text I draw after I add my UIView is still at the "bottom" of the user interface?
Thanks in advance.
iOS, like OS X, uses a compositing window manager. Adding and removing UIViews sets their position in the view hierarchy; when and how they're drawn is managed separately. There is no guaranteed relation between when a view is added and when it'll be drawn, and no reason to guarantee one. The content of a view is cached and composited as required from that copy.
If you want to do custom drawing, create a custom UIView subclass, add it to the hierarchy according to where you want it to appear and do your drawing in drawRect: or one of the other override points if you want to render off thread.