In the following code when i select a line, a delete menu shows up. Now after this when i start drawing a new line (leaving the delete menu as-is), the delete menu on top of the first one is supposed to disappear. Thats because while i'm starting to draw the second line, the uimenucontroller singleton object destroys as the pointer pointing it is set to nil. This is what is supposed to happen. But apparently its not.. When i log the pointer in drawRect method, it does show up as nil though.. So why is the menu still showing up? Here is the code---
-(void)tap:(UIGestureRecognizer *)sender{
NSLog(@"Recognized tap-%@",sender);
CGPoint p= [sender locationInView:self];
selectedLine= [self lineAtPoint:p];//Not going to return anything with just a tap which draws a (non drawable) point and not a line.
[linesInProcess removeAllObjects]; //Avoid adding a new line while performing the tap gesture
if (self.selectedLine) {
NSLog(@"setting up delete menu");
[self becomeFirstResponder];
menu= [UIMenuController sharedMenuController];
// create a "Delete" menu item
deleteItem= [[UIMenuItem alloc] initWithTitle:@"Delete" action:@selector(deleteLine:)];
[menu setMenuItems:@[deleteItem]];
// Tell the menu where it should come from and show it.
[menu setTargetRect:CGRectMake(p.x, p.y, 2, 2) inView:self];
[menu setMenuVisible:YES animated:YES];
}
else{
// Hide the menu if no line is selected
[menu setMenuVisible:NO animated:YES];
}
[self setNeedsDisplay];
NSLog(@"test");
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"%@",NSStringFromSelector(_cmd));
// Silver challenge
selectedLine=nil;
menu=nil
int i=0;
for (UITouch *touch in touches) {
NSLog(@"%dth iteration using touch- %@",++i,touch);
// Use the touch object [packed in an NSValue] as the key
NSValue *key= [NSValue valueWithNonretainedObject:touch];
NSLog(@"key-%@ touch-%@",key,touch);
// Create a line for the value
CGPoint loc= [touch locationInView:self];
Line *newLine= [[Line alloc] initWithLocation:loc];//Line to be drawn..Plus, setting begin and end pts. happens here.
NSLog(@"new line- %@",newLine);
// put pair in dictionary
[linesInProcess setObject:newLine forKey:key];
}
}
- (void)drawRect:(CGRect)rect
{
NSLog(@"%@",NSStringFromSelector(_cmd));
// Drawing code
CGContextRef context= UIGraphicsGetCurrentContext();
CGContextSetLineCap(context, kCGLineCapRound);//style of the line-endpoints
NSLog(@"delete menu-%@",menu);
// Draw complete lines in black
[[UIColor blackColor] set];
for (Line *line in self.rootObj.completeLines) {
NSLog(@"Iterating over array");
NSLog(@"complete line- %@",line);
NSLog(@"begin pt.- (%f, %f) and end pt.- (%f, %f)",[line begin].x,[line begin].y,[line end].x,[line end].y);
CGContextMoveToPoint(context, [line begin].x, [line begin].y);
CGContextAddLineToPoint(context, [line end].x, [line end].y);
CGContextStrokePath(context);
}
// Draw lines in process in red..
[[UIColor redColor] set];
for (NSValue *v in linesInProcess) {
NSLog(@"Iterating over dictionary");
Line *line= [linesInProcess objectForKey:v];
NSLog(@"line being drawn- %@",line);
CGContextMoveToPoint(context, [line begin].x, [line begin].y);
CGContextAddLineToPoint(context, [line end].x,[line end].y);
CGContextStrokePath(context);
}
NSLog(@"selected line: %@",self.selectedLine);
// Change the color of selected line. Redraw that line as green colored.
if (selectedLine) {
NSLog(@"reseting color");
[[UIColor greenColor] set];
CGContextMoveToPoint(context, [selectedLine begin].x, [selectedLine begin].y);
CGContextAddLineToPoint(context, [selectedLine end].x, [selectedLine end].y);
CGContextStrokePath(context);
}
NSLog(@"drawing ended");
}
I'm solving this problem from the Big Nerd Ranch Guide. In the touchesBegan: and tap: method, 'menu' is used.It is an ivar. Pls note that touchesBegan: is not calling setNeedsDisplay. This is just a code snippet. In the actual program setNeedsDisplay has been called from other methods like touchesMoved: and touchesEnded:. I just want to know as to why the menu on the view stays, when clearly i'm destroying it in touchesBegan: method by setting its pointer to nil.
The control flow is something like this during and after the 1st line is selected to show up the delete menu:
Since your controller is a Singleton, it probably has a strong
reference as static
for an instance of itself, and that instance is what is being returned to your pointer when you call sharedInstance
.
(What I assume the sharedMenuController
method is)
+ (id)sharedMenucontroller {
static UIMenuController *sharedMenuController = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMenuController = [[self alloc] init];
});
return sharedMyManager;
}
This means that arc wont clean it just by setting your pointer to that singleton's static variable as nil.
If you just want to hide it, call setVisible:NO
on it, is the simplest way.