何日もの間、問題に苦しんでいます。ここで答えが得られることを願っています。このリンクを使用して、フリーハンドの描画をスムーズにしました。このコードでは、線の幅と色を設定できましたが、元に戻るでうまく機能しているこのリンクを使用して元に/やり直し機能を含めると、非常に難しいと感じていますが、フリーハンドでの描画はスムーズではありません。
いくつかの調査とコーディングの後で、私はそれが元に戻る/やり直しを妨げると思う描画のキャッシングであることを知ることになっています。
最初のリンクに「CachedLIView.h/m」というファイルがあります。これを使用して元に戻る/やり直しを含めようとすると、次の方法で見つかりました。
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event // (2)
{
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
[path addLineToPoint:p];
[self drawBitmap]; // (3)
[self setNeedsDisplay];
[path removeAllPoints]; //(4)
}
このメソッドはdrawBitMapを呼び出しています。このメソッドは、ユーザーが指を離すたびに一時的な画像を実際に生成し、同時に「パス」からポイントを削除します。
- (void)drawBitmap // (3)
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0);
[[UIColor blackColor] setStroke];
if (!incrementalImage) // first draw; paint background white by ...
{
UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object
[[UIColor greenColor] setFill];
[rectpath fill]; // filling it with white
}
[incrementalImage drawAtPoint:CGPointZero];
//[path stroke];
for (UIBezierPath *_path in pathArray)
[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
元に戻す/やり直しができるように、すべてのパスを配列に保存しています。(2番目のリンクからこのアイデアを採用しました)。
以下は、元に戻る/やり直しを含めるために変更したこのファイルの完全なコードです。
#import "CachedLIView.h"
@implementation CachedLIView
{
UIBezierPath *path;
UIImage *incrementalImage; // (1)
}
- (id)initWithFrame:(CGRect)frame // (1)
{
if (self = [super initWithFrame:frame])
{
[self setMultipleTouchEnabled:NO]; // (2)
// [self setBackgroundColor:[UIColor whiteColor]];
// path = [[UIBezierPath alloc] init];
// [path setLineWidth:3];
pathArray=[[NSMutableArray alloc]init];
bufferArray=[[NSMutableArray alloc]init];
[self drawBitmap];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
NSLog(@"in drawrect pathArray[count]: %d", pathArray.count);
[incrementalImage drawInRect:rect]; // (3)
//[[UIColor blackColor] setStroke];
//[path stroke];
for (UIBezierPath *_path in pathArray)
[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
path = [[UIBezierPath alloc] init];
path.lineWidth = 3;
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
[path moveToPoint:p];
[pathArray addObject:path];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
[path addLineToPoint:p];
[self setNeedsDisplay];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event // (2)
{
UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
[path addLineToPoint:p];
[self drawBitmap]; // (3)
[self setNeedsDisplay];
[path removeAllPoints]; //(4)
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesEnded:touches withEvent:event];
}
- (void)drawBitmap // (3)
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0);
[[UIColor blackColor] setStroke];
if (!incrementalImage) // first draw; paint background white by ...
{
UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object
[[UIColor greenColor] setFill];
[rectpath fill]; // filling it with white
}
[incrementalImage drawAtPoint:CGPointZero];
//[path stroke];
for (UIBezierPath *_path in pathArray)
[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
#pragma mark - undo/redo
-(void)undoButtonClicked
{
if([pathArray count]>0){
UIBezierPath *_path=[pathArray lastObject];
[bufferArray addObject:_path];
[pathArray removeLastObject];
[self drawBitmap];
[self setNeedsDisplay];
}
}
-(void)redoButtonClicked
{
if([bufferArray count]>0){
UIBezierPath *_path=[bufferArray lastObject];
[pathArray addObject:_path];
[bufferArray removeLastObject];
[self drawBitmap];
[self setNeedsDisplay];
}
}
@end
.hファイルは次のとおりです。
#import <UIKit/UIKit.h>
@interface CachedLIView : UIView
{
NSMutableArray *pathArray;
NSMutableArray *bufferArray;
UIBezierPath *myPath;
}
-(void)undoButtonClicked;
-(void)redoButtonClicked;
@end
私を助けてください。私が間違っていること。pathArrayカウントは正しく機能しています。ただし、画面に元に戻す/やり直しの効果を表示することはできません。