drawRect Doesn't want to draw anything - ios

I have a ViewController on storyboard. I have used the interface builder to set a toolbar at the bottom of the screen. I have set the custom view to a view overrides drawRect. However, for the life of me, I cannot get anything ever to show up on screen called from that drawRect. drawRect itself is called just fine, but nothing shows up on screen.
Also, I have this ViewController with a method that uses AVCaptureSession to toggle its background to a live view from camera input. I had suspected that this might have been the cause for error, but after removing all references of AVCaptureSession, I still cannot get this to work.
Sorry for my writing and/or lack of logic, I don't have any sleep right now.
Edit: Here is a small example of code that won't work. Every method inside gets called, but nothing is to show.
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
// Draw them with a 2.0 stroke width so they are a bit more visible.
CGContextSetLineWidth(context, 2.0);
CGContextMoveToPoint(context, 0,0); //start at this point
CGContextAddLineToPoint(context, 100, 100); //draw to this point
// and now draw the Path!
CGContextStrokePath(context);
}

The documentation for UIView says to not call [super drawRect] if you're overriding UIView. Remove that call! It's been known to cause strange behaviour.
According to the docs:
If you subclass UIView directly, your implementation of this method
does not need to call super. However, if you are subclassing a
different view class, you should call super at some point in your
implementation.

Related

How to make CGContextDrawPath draw on a nested subview?

I'm new to context concept in Apple iOS programming. Currently, I'm thinking in views. I want to draw an arc using the easiest method possible, and then I found this question and answer. But then I'm confused with context concept. I thought to draw something, I will need to call the drawing function and supply the view where I want the drawing function to draw. But in there, I got confused with UIGraphicsGetCurrentContext(). What "current context" is that? Is it the UIScreen.mainScreen()? How if I want to set the "current context" to a view inside a UICollectionViewCell, so that all the pixel drawn will be relative to the view? Can I do that?
The way you draw in CocoaTouch is to subclass UIView to create a custom view and implement the drawRect:(CGRect)rect method. Put your drawing code inside drawRect. Something like:
-(void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGPathRef path = CGPathCreateWithRect(rect, NULL);
[[UIColor blueColor] setStroke];
CGContextSetLineWidth(context, 4.0);
CGContextAddPath(context, path);
CGContextDrawPath(context, kCGPathFillStroke);
CGPathRelease(path);
}
You can put your custom UIView inside of a UICollectionViewCell if you want.

Having trouble with graphics context

I am working on multiple terminal screen app, for that I have a custom UIView subclass for the terminal views. Every time I need a new terminal screen, I prepare a new view.
This view class draws the text using a CGContextRef. The problem I am facing is that the context only draws the text of the last view that was created, e.g. if I have 3 terminals and drawing on first/second, it still draws on the third one.
My code so far:
-(void)drawRect:(CGRect)rect{
contxt = UIGraphicsGetCurrentContext();
}
-(void)setNeedsDisplayInRect:(CGRect)rect{
UIGraphicsPushContext(contxt);
//CGContextSaveGState(contxt);
CGContextSetTextMatrix(contxt,CGAffineTransformIdentity);
if (translated) {
CGContextScaleCTM(contxt, 1, -1);
translated = NO;
}
CGRect rectConvert = CGRectMake(rect.origin.x, rect.origin.y-screenWindowHeight, rect.size.width, rect.size.height);
CGContextSetFillColorWithColor(contxt, bgColor.CGColor);
CGContextFillRect(contxt, rectConvert);
if (!isDeleteChar) {
CGContextSetFillColorWithColor(contxt, fgColor.CGColor);
[displayString drawInRect:rectConvert withFont:font lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
}
if (ul == EXTENDED_5250_UNDERLINE) {
CGContextSetFillColorWithColor(contxt, fgColor.CGColor);
[#"_" drawInRect:rectConvert withFont:font lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
}
//CGContextRestoreGState(contxt);
UIGraphicsPopContext();
}
Finally I solved it by own using
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]]; just after setNeedsDisplay.
First and foremost, you should not be doing drawing in the -setNeedsDisplayRect: method, all of your drawing code should be in drawRect: instead. This way, the main runloop can better organize redrawing of the views.
Second, I suspect the variables that you are using for your CGRect conversions are faulty and are drawing outside of the view bounds. You can test this premise by clipping the view's drawing (set layer.masksToBounds to YES for the views)
If this is the case, you can adjust them to be relative to the view (all drawing within the view should be relative to its bounds, not its frame). When drawing the view, assume a canvas that stretches the bounds property of the view, i.e origin at (0,0) and size of (width,height).
Now, it is worth also discussing what the rect property passed to drawRect: really is, it is not guaranteed to be the entire bounds of the view, so you should not assume that. It is the portion of the view that needs to be redrawn, however, common practice (for simpler views) is to ignore that parameter and just redraw the entire view. Once this becomes too expensive (or you need the drawing to be more optimal), you can look into doing partial redraws of your view.
All in all, it is difficult to diagnose the full problem without seeing the entire UIView subclass code.

arc/curve overlay at elevation/bearing over iphone camera

Folks,
I am looking for pointers/directions on what should I learn/read about in order to accomplish what I need to. I am NOT looking for a whole solution/answer (unless you have that ready of course :)).
My problem is that I would like to present an overlay over a camera/video view. The overlay consists of an ARC/curve that has dots all over it. The overlay will be there but it will only show when the user tilts the device to elevation X (degrees) and bearing Y.
A couple of examples can be seen in the following two videos on youtube:
http://www.youtube.com/watch?v=lRLpKZMCRHo at time 0:15 to 0:50 and
http://www.youtube.com/watch?v=oemvZl151eY at time 0:14 till end (0:48)
I have never used quartz/graphics/spritekit and I don't even know if these are useful to do this hence I don't know where to start…
Appreciate your assistance. Thanks in Advance!
Simplest approach is with quartz. Plot your arc or curve using CGContext draw functions into a UIView which you lay over the camera view. This is done easily inside UIView's drawRect: method, since you can easily retrieve a CGContext of the particular UIView. To better explain this, here's an example:
//
// PlotView.m
// testApp
//
// Created by Me on 10/20/13.
// Copyright (c) 2013 Me. All rights reserved.
//
#import "PlotView.h"
#implementation PlotView
-(void)drawRect:(CGRect)rect
{
//The CGContext for this UIView instance
CGContextRef context = UIGraphicsGetCurrentContext();
//Set the draw style
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
//Add elements to draw
CGContextAddArc(context, CGRectGetMidX(rect), CGRectGetMidY(rect), CGRectGetWidth(rect)/2, M_PI_4, 3*M_PI_4, YES);
//commit draw
CGContextDrawPath(context, kCGPathStroke);
//additional parts with different draw setup
CGContextSetLineWidth(context, 5);
CGContextAddEllipseInRect(context, CGRectMake(10, 10, 50, 50));
CGContextDrawPath(context, kCGPathFillStroke);
}
#end
You can plot everything in this single view and just adjust its position according to the device movement. Also you can hide/show the view normally (changing alpha or hidden property).
To trigger an update (when e.g. satelittes change position) call the setNeedsDisplay or setNeedsDisplayInRect: method. For optimization's sake if necessary use the rect parameter in the latter (and also the same parameter in the drawRect method) to trigger redraw only on parts of the view where it is necessary (and also draw only in this rectangle).
Regarding the curve you need to display: I'm sure you'll find a suitable CGContextAdd... function with the shape you need to draw, whether it's an arc, a set of straight lines or a Bezier curve.

Could anyone explain drawrect and context animation?

I'm quitely new for the iOS, so I don't know much of it.
I know how to make UIView (and its childviews) but I don't know about drawRect
I make a class which inherits from UIView and make subviews in initWithFrame method.
I want to draw a NSString using CGContext after adding subViews and move it outside of view after 5 seconds.
Could anyone explain when drawRect is called and how to move it?
This code helps you to draw a NSString which was stored before in _content:
- (void)drawRect:(CGRect)rect{
CGContextRef context = UIGraphicsGetCurrentContext();
[_content drawInRect:rectForFrame
withFont:[UIFont fontWithName:kFontMedium size:15.0f]
lineBreakMode:NSLineBreakByWordWrapping
alignment:NSTextAlignmentCenter];
}
To let the element slide out, you would have to call a NSTimer after your UIView was shown (Maybe with a delay using performSelector:withObject:afterDelay:) and change the attributes of the CGRect you want to write the NSString inside. You can just setup a method which will be called by your NSTimer in a specific interval which also updates the UIView.
- (void)updateView{
//create a rect
rectForFrame = CGRectMake....;
[self setNeedsDisplay];
}
One way to do it would be to draw the string and then start an NSTimer. Start a 5 second timer, and when it fires, then you can move it.
As for when -drawRect: is called - it's called whenever your view needs to be updated. It will be called when your view is first displayed by the OS. After that, it will usually be called when it changes size or shape, or when your code calls [myView setNeedsDisplay:YES], which tells the OS to update it.

Empty drawRect implementation causes memory warning

I have a UIView on which I draw a UIBezierPath by finger.
When I rezoom the view (say after a path is drawn) a redraw function is triggered, which rescales the BezierPath:
- (void)redrawPathsWithScale:(float)scale
{
[_path applyTransform:CGAffineTransformMakeScale(scale, scale)];
[self setNeedsDisplay];
}
setNeedsDisplay causes drawRect to get called.
Now every time I zoom in to a absolute scale somewhere near x6 I immediately get a memory warning, and the App crashes.
My drawRect method looks like this:
- (void)drawRect:(CGRect)rect
{
[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}
The Curious thing is: Not implementing drawRect at all removes the memory warning. Implementing an empty drawRect still causes a crash!
Does adding [super drawRect:rect]; make any difference?
The Apple Documentation for drawRect states:
If you subclass UIView directly, your implementation of this method does not need to call super. However, if you are subclassing a different view class, you should call super at some point in your implementation.
If you're subclassing UIView, you should be fine but it might be worth checking this just in case.

Resources