Best way to draw line between fix CGPoint and moving UIView object's center point - ios

I have a UIView subclass object that animates and therefore changes its position over time as a subview in my UIViewController's view. Actually my moving UIView subclass is just an image of a ball and it's moving as if it was hanging down from my devices screens top border. But to be a real pendulum I'd like to also draw a line between my ball and the CGPoint it hangs down from on top of my screen.
My idea was to just draw a line every time the UIView changes its position. But as the moving is done within an iOS API (I'm just calling something like [myBallView swing]) I can't do this at the same place the movement is happening. I'm actually not animating the view myself.
The only solution I have in my mind to solve my issue is pretty bad: subclassing UIView, adding it as a superview to my moving UIView and adding a line every time drawRect is called. But I'm not even sure drawRect is going to be called there. Either way, there must be a better solution for this.
Does anyone know a good solution to my problem?

Making a custom subclass of UIView as the superview is reasonable.
However, rather than drawing the line yourself, I would suggest implementing +layerClass in your custom view, and making the backing layer a CAShapeLayer.
Then you can create a CGPath in the view's shape layer that is a line, and manipulate the start and end points of the line when your other view's center moves. Shape layers are designed to draw as part of the screen update process, and you could even make the change animate by changing the endpoints of the path with a CABasicAnimation.

Related

How to fil rectangular ares in the screen with good performance in ios

I'm making simple number coloring game (like sandbox, pixel art, unicorn, etc) and came across a problem. I tried various methods of filling rects in the screen.
At first i created a backgroundView(a simple UIView) which had 2500 subviews(also UIViews), each one had size = (CGSize){50,50}. Added a tap gesture recognizer, detected which view should be filled, and simply changed the background color of that view. But when i placed the backgroundView in the scrollView, the scroll and zooming were awful.
Tried same thing but this time each rectangle was a CALayer. So a backgroundView, which had 2500 sublayers(each was a CALayer with 50,50 size) - zoom and scroll was also awful.
Tired to use custom drawing with overriding drawRect method in UIView subclass or drawInContext in CALayer subclass(i was filling rects with CGContext), this time problem was also caused by the zooming and scrolling. Because i needed to update every rect when user zooms, it was triggering a lot of drawRect calls, and performance was also bad.
Any thoughts how can i fill rects in the screen ?
Explanation
Yup! Adding 2,500 tiny UIViews to a scroll view can destroy performance. I wouldn't use that approach, but if you do, at least make sure that subview_N.opaque = YES; on all subviews to disable compositing.
The CALayer approach that you described is basically the same as the UIView approach because views are backed by CoreAnimation layers (see -[UIView layer]).
The best options for drawing thousands of rectangles to the screen on iOS without decimating frame rate, is to use one of the following approaches:
Draw directly using CoreGraphics
Draw directly using OpenGL (extremely involved)
Use a layout engine such as UICollectionViewLayout
Now, you said you had tried overriding -[UIView drawRect:], but you didn't provide any example code for us to checkout. Please update your question with actual code for method #3 if you want more specific feedback. It's very likely that something is wrong with the drawRect code you created. CoreGraphics can definitely draw thousands of squares on screen without dragging frame rate down that badly.
One Solution
I recently released a project, YMTreeMap, that draws thousands of rectangles into a UIView to create financial TreeMaps. It's in Swift, not Objective-C, but the underlying concepts are the same. For this, I created a custom UICollectionViewLayout that lets Apple's well tested UICollectionView class handle the nitty gritty of selective drawing, zooming and animation.
The example UIViewController code in the YMTreeMap project shows how to draw thousands of colored rectangles to the screen if all you know is their location and size. This sounds like what you are doing. Since you're also scrolling and zooming, this solution might be perfect for you because UICollectionView has native support for both of those.

Swift xcode horizontal line

I wonder what the best way to create a horizontal line is?
I have a few labels / text and I would like to add a horizontal line between them. More or less like a when using twitter bootstrap.
Right now I am using a UIview and setting it as 1 in height with a black background color. But I guess this isnt the best way to do it?
That is the way to do it in iOS. UIView is the class which represent something to be shown on the screen. Every UI component is direct or indirect descendant of UIView. So, you should use UIView.
UIView is backed by CALayer to render the content to screen. You could also use CALayer, CAShapeLayer or other layer classes to create a border. But, I would not recommend to use CALayer just to show a border as it is simpler to use UIView with height of 1, on the top of that, you get some nice addition such as autolayout. If you use CALayer, you will have to set frame to layer at appropriate time when the view bounds change. It could also be tricky due to some intrinsic animation within CALayer.

UIView animation in drawrect

I need to continuously change the color of all the lines I draw in a UIView. And I drew all the lines within the drawrect method to assign colors. Now I need to animation and change the colors as long as the view is shown. Is there a way to do it? Thanks a lot!
Look into using one instance of CAShapeLayer for each of the lines, instead of drawing them in drawRect:. You can animate changes to each layer's path and strokeColor properties as necessary.
EDIT
If you're just drawing horizontal lines, you may be better off simply using a UIView for each. Set the backgroundColor instead of implementing drawRect:. You can animate both the frame property and the backgroundColor property using +[UIView animateWithDuration:animations:] (or the more powerful variants of it). This is generally simpler than messing around with Core Animation.
Live and learn. Animations are better done outside of -drawRect:
Change your "lines" to individual UIView instances added as (preferably opaque) subviews to your view. You'd then set the appropriate backgroundColor on the view.
You can then use a simple UIView animation to animate them.

Multiple UIView transformation animations, one repeats, the other does not

I have a UIImageView whose instance has a repeating pulse-like animation.
I want this UIImageView to move with the force of the accelerometer. To do this I have added another animation, this time a translation.
However, once this translation happens, it stops the pulse, even when its not animating.
As these two animations are separate, I cannot use the CGAffineTransformConcat method to combine both animations.
I have tried adding one to the UIView and one to the layer property of the same UIView but it does not work.
I have also tried adding the movement directly to the frame of the view, however, this just causes my view to disobey the constraint constraining it to the center x of the superview.
Does anyone use/know of a work around to this?
Thanks as always!

How to move object

i am working on a project in which i have to provide user facility to draw an circle . i have done this part. But new requirement is that user can move it at any his desire position.I have no idea about it.please help me.
Make a subview of UIView. In it, override drawRect: to draw your circle. Add it to a superview that is the size of the screen. Then, give your view a UIPanGestureRecognizer. Set the target/action to a method on your circle view, and in that method set the view's frame to have an origin at the gesture recogniser's locationInView:.
If you need more specific help than this, feel free to post some code that you're having trouble with.

Resources