我正在尝试将我在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 app中的(工作)代码:
//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建议的那样,这是paintselectionrectangle
的iOS代码:
-(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];
}
答案 0 :(得分:0)
您不应在paintSelectionRectangle
中致电touchesEnded:withEvent:
。此方法执行绘图操作,并且您没有图形上下文。只需将setNeedsDisplay
发送到需要重绘的视图即可。
另外我认为手动调用touchesBegan:withEvent:
是一个坏主意。
编辑:我仔细研究了您的代码以及您尝试实现的目标。我将创建一个绘制选择矩形的UIView子类。用bezier路径填充整个边界:
-(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为帧更改设置动画。