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

電話paintSelectionRectangleをかけないでくださいtouchesEnded: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 に答える