即使指针设置为nil,UIMenuItem也会继续显示

时间:2014-07-06 17:45:52

标签: objective-c cocoa-touch uimenucontroller

在以下代码中,当我选择一行时,会显示删除菜单。在此之后,当我开始绘制一个新行(将删除菜单保持原样)时,第一个顶部的删除菜单应该会消失。那是因为当我开始绘制第二行时,uimenucontroller单例对象会在指向它的指针被设置为nil时销毁。这是应该发生的事情。但显然它不是..当我在drawRect方法中记录指针时,它确实显示为nil ..那么为什么菜单仍然显示?这是代码---

 -(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");
}

我从Big Nerd Ranch Guide解决了这个问题。在touchesBegan:并点按:方法,'菜单'是用的。它是一个伊娃。请注意touchesBegan:不调用setNeedsDisplay。这只是一个代码段。在实际程序中,setNeedsDisplay已经从其他方法调用,如touchesMoved:和touchesEnded:。我只是想知道为什么视图上的菜单保持不变,当我明确地在touchesBegan:方法中将其指针设置为nil时将其销毁。

在选择第一行显示删除菜单期间和之后,控制流程如下:

  1. 点击消息,并创建菜单对象并完成所有相关设置。
  2. 操作: - 选择第一行,删除菜单显示在其上。
  3. 动作: - 然后(保留第一行的删除菜单),正在绘制第二行。
  4. touchesBegan:消息传递给视图,菜单指针设置为nil。
  5. tap方法可能会也可能不会被调用,如果是,那么if块就不会被运行,因此菜单'永远不会重新实施。
  6. 最终drawRect:传递消息并实现所有行和设置。
  7. 第一行的删除菜单按原样保留。 (这就是问题所在)

1 个答案:

答案 0 :(得分:0)

由于你的控制器是一个Singleton,它可能有一个strong引用作为static的自身实例,而那个实例是你调用{{1}时返回指针的实例}。 (我假设sharedInstance方法是什么)

sharedMenuController

这意味着只要将指向该单例的静态变量的指针设置为nil,arc就不会清除它。 如果您只想隐藏它,请在其上调用+ (id)sharedMenucontroller { static UIMenuController *sharedMenuController = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedMenuController = [[self alloc] init]; }); return sharedMyManager; } ,这是最简单的方法。