0

我正在尝试将我在 Cocoa 中创建的 Sudoku 应用程序移植到 iOS,但我无法将 Mac 应用程序中的 mouseDown 事件转换为 iOS 上的 touchBegan 事件。

我在父视图中创建了一个子视图,其中绘制了网格并且数独游戏的所有初始值都已到位。每当我尝试在模拟器中点击一个空方块来更新值时,我的控制台都会给我这些错误:

Mar 24 14:59:56 Macintosh-94.local SudokiOS[95817] <Error>: CGContextSetFillColorWithColor: invalid context 0x0
Mar 24 14:59:56 Macintosh-94.local SudokiOS[95817] <Error>: CGContextSaveGState: invalid context 0x0
Mar 24 14:59:56 Macintosh-94.local SudokiOS[95817] <Error>: CGContextSetFlatness: invalid context 0x0
Mar 24 14:59:56 Macintosh-94.local SudokiOS[95817] <Error>: CGContextAddPath: invalid context 0x0
Mar 24 14:59:56 Macintosh-94.local SudokiOS[95817] <Error>: CGContextDrawPath: invalid context 0x0
Mar 24 14:59:56 Macintosh-94.local SudokiOS[95817] <Error>: CGContextRestoreGState: invalid context 0x0

这是我的 mac 应用程序中的(工作)代码:

//SudokuView.m
-(void)paintSelectionRectangle
{
    CGFloat thirdWidth = self.bounds.size.width / 3.0;
    CGFloat thirdHeight = self.bounds.size.height / 3.0;
    CGFloat ninthWidth = thirdWidth / 3.0;
    CGFloat ninthHeight = thirdHeight / 3.0;

    NSRect selectionRect = NSMakeRect(_selectionCellX * thirdWidth + _selectionX * ninthWidth,
                                      _selectionCellY * thirdHeight + _selectionY * ninthHeight,
                                      ninthWidth, ninthHeight);

    NSColor* selectionColor = [NSColor colorWithSRGBRed: 0.0 green: 0.0 blue: 1.0
                               alpha: 0.5];
    [selectionColor setFill];

    NSBezierPath* selectionPath = [NSBezierPath bezierPathWithRoundedRect: selectionRect
                                                                  xRadius: ( ninthWidth / 4.0 )
                                                                  yRadius: ( ninthHeight / 4.0 )];
    [selectionPath fill];
}

- (void)drawRect:(NSRect)dirtyRect
{

    ...

    if(_haveSelection)
    {
        [self paintSelectionRectangle];
    }
    ...
}
.
.
.
-(void)mouseDown:(NSEvent *)event
{
    NSPoint location = [event locationInWindow];
    CGFloat thirds = self.bounds.size.width / 3;
    CGFloat ninths = thirds / 3;

    _selectionCellX = (UInt32)(location.x/thirds);
    _selectionCellY = (UInt32)(location.y/thirds);
    _selectionX = (UInt32)((location.x - (_selectionCellX * thirds)) / ninths);
    _selectionY = (UInt32)((location.y - (_selectionCellY * thirds)) / ninths);

    _haveSelection = YES;


    if ([self._windowController isOriginalValueAtCellX:_selectionCellX andCellY:_selectionCellY xIndex:_selectionX yIndex:_selectionY] == NO)
    {
        _haveSelection = YES;
    }
    else
    {
        _haveSelection = NO;
    }
    [self setNeedsDisplay:YES];
}

这就是在 iOS 应用程序中不起作用的地方

//SudokiOSViewController.m
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch* touch = [[event allTouches] anyObject];
    CGPoint location = [touch locationInView:self.sudokuSubview];
    CGFloat thirds = sudokuSubview.bounds.size.width / 3;
    CGFloat ninths = thirds / 3;


    _selectionCellX = (UInt32)(location.x/thirds);
    _selectionCellY = (UInt32)(location.y/thirds);
    _selectionX = (UInt32)((location.x - (_selectionCellX * thirds)) / ninths);
    _selectionY = (UInt32)((location.y - (_selectionCellY * thirds)) / ninths);
    _haveSelection = YES;
    if ([ourView._ourViewController isOriginalValueAtCellX:_selectionCellX andCellY:_selectionCellY xIndex:_selectionX yIndex:_selectionY] == NO)
    {
        _haveSelection = YES;
    }
    else
    {
        _haveSelection = NO;
    }

}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesBegan:touches withEvent:event];
    [sudokuSubview setNeedsDisplay];
    [self paintSelectionRectangle];
}

我很难理解我是否应该只使用 touchBegan 和 touchEnded 或 UIGestureRecognizer。我也不明白为什么要调用 CGContext 。对此的任何帮助将不胜感激。谢谢!

更新:正如 mrueg 所建议的,这里是 iOS 代码paintselectionrectangle

-(void)paintSelectionRectangle
{
    CGFloat thirdWidth = self.bounds.size.width / 3.0;
    CGFloat thirdHeight = self.bounds.size.height / 3.0;
    CGFloat ninthWidth = thirdWidth / 3.0;
    CGFloat ninthHeight = thirdHeight / 3.0;

    CGRect selectionRect = CGRectMake(_selectionCellX * thirdWidth + _selectionX * ninthWidth,
                                      _selectionCellY * thirdHeight + _selectionY * ninthHeight,
                                      ninthWidth, ninthHeight);

    UIColor* selectionColor = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.5];
    [selectionColor setFill];

    UIBezierPath* selectionPath = [UIBezierPath bezierPathWithRoundedRect:selectionRect cornerRadius:(ninthWidth/4.0)];
    [selectionPath fill];
}
4

1 回答 1

0

你不应该打电话paintSelectionRectangletouchesEnded:withEvent:。此方法执行绘图操作,并且您在那里没有图形上下文。只需发送setNeedsDisplay到需要重绘的视图。

另外我认为touchesBegan:withEvent:手动调用是个坏主意。

编辑:我仔细查看了您的代码以及您尝试实现的目标。我将创建一个绘制选择矩形的 UIView 子类。只需用贝塞尔路径填充整个边界:

-(void)drawRect:(CGRect)rect
{
    UIColor* selectionColor = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:0.5];
    [selectionColor setFill];

    CGRect roundedrect = self.bounds;
    CGFloat cornerRadius = self.bounds.size.width / 36;
    UIBezierPath* selectionPath = [UIBezierPath bezierPathWithRoundedRect:roundedRect
                                                             cornerRadius:cornerRadius];
    [selectionPath fill];
}

将该视图的一个实例添加到您的主视图并将其hidden属性设置为 YES。

touchesEnded:withEvent:确定选择矩形时,设置选择视图的框架并设置hidden为 NO,如果您检测到选择:

CGRect selectionRect = CGRectMake(_selectionCellX * thirdWidth + _selectionX * ninthWidth,
                                  _selectionCellY * thirdHeight + _selectionY * ninthHeight,
                                  ninthWidth, ninthHeight);
[selectionSubview setFrame: selectionRect];

[selectionSubview setHidden: !_haveSelection];

如果您愿意,您还可以使用 CoreAnimation 为帧更改设置动画。

于 2013-03-24T22:38:54.480 回答