2013-03-18 37 views
1

我创建了NSView的子类来创建包含NSTextView的自定义UI。因此我使用drawRect方法绘制我的UI。我还创建了NSImageView的子类来获取mousedown事件。每当我点击进入我的Subclassed NSImageView时,我的视图的drawRect方法在无限循环中被调用,我无法弄清楚为什么。建立自定义用户界面对我来说是新的,所以也许我做的事情本质上是错误的?NSView的子类drawRect在无限循环中调用

TWIComposeFrameView.m:

#import "TWIComposeWindowFrameView.h" 
#import "TWIImageView.h" 

@implementation TWIComposeWindowFrameView 

#pragma mark draw Rect of the View 

// 
// drawRect: 
// 
// Draws the frame of the window. 
// 
- (void)drawRect:(NSRect)rect 
{ 
    //// Color Declarations 
    NSColor* mainClrWhite = [NSColor colorWithCalibratedRed: 0.954 green: 0.954 blue:  0.954 alpha: 1]; 
    NSColor* transpGrey = [NSColor colorWithCalibratedRed: 0.224 green: 0.224 blue: 0.224 alpha: 0.745]; 
    NSColor* composeClrGrey = [NSColor colorWithCalibratedRed: 0.858 green: 0.842 blue: 0.842 alpha: 1]; 

    //// Abstracted Attributes 
    NSRect composeRectRect = NSMakeRect(20, 70, 475, 210); 
    NSRect attachmentRectRect = NSMakeRect(499, 195, 85, 85); 


    //// transpRect Drawing 
    NSBezierPath* transpRectPath = [NSBezierPath bezierPathWithRoundedRect: NSMakeRect(1, 0, 599, 299) xRadius: 10 yRadius: 10]; 
    [transpGrey setFill]; 
    [transpRectPath fill]; 


    //// mainRect Drawing 
    NSBezierPath* mainRectPath = [NSBezierPath bezierPathWithRoundedRect: NSMakeRect(10, 10, 580, 280) xRadius: 10 yRadius: 10]; 
    [mainClrWhite setFill]; 
    [mainRectPath fill]; 


    //// composeRect Drawing 
    NSBezierPath* composeRectPath = [NSBezierPath bezierPathWithRoundedRect: composeRectRect xRadius: 10 yRadius: 10]; 
    [composeClrGrey setFill]; 
    [composeRectPath fill]; 


    //// attachmentRect Drawing 
    NSBezierPath* attachmentRectPath = [NSBezierPath bezierPathWithRoundedRect: attachmentRectRect xRadius: 10 yRadius: 10]; 
    [mainClrWhite setFill]; 
    [attachmentRectPath fill]; 
    [composeClrGrey setStroke]; 
    [attachmentRectPath setLineWidth: 1]; 
    [attachmentRectPath stroke]; 
} 

- (id)initWithFrame:(NSRect)rect 
{ 
    if (![super initWithFrame:rect]) 
     return nil; 

    NSColor* composeClrGrey = [NSColor colorWithCalibratedRed: 0.858 green: 0.842 blue: 0.842 alpha: 1]; 
    NSRect composeRectRect = NSMakeRect(20, 70, 475, 210); 
    NSRect attachmentRectRect = NSMakeRect(499, 195, 85, 85); 
    //// Add Controls 
    [self addComposeTextView:composeClrGrey composeRectRect:composeRectRect]; 
    [self addAttachmentImageView:attachmentRectRect]; 
    return self; 
} 

#pragma mark - 
#pragma mark Add Controls to View 

// 
// Create and Add the Compose TextView 
// 
- (void)addComposeTextView:(NSColor *)composeClrGrey composeRectRect:(NSRect)composeRectRect 
{ 
    NSTextView *composeTextView; 
    if (composeTextView == nil) 
    { 
     composeTextView = [[NSTextView alloc] initWithFrame:composeRectRect]; 
     [composeTextView setBackgroundColor:composeClrGrey]; 
     [composeTextView setFont:[NSFont fontWithName:@"Helvetica" size:18]]; 
     [composeTextView setRichText:NO]; 
     [self addSubview:composeTextView]; 
    } 
} 

// 
// Create and Add the Attachemant ImageView 
// 
- (void)addAttachmentImageView:(NSRect)attachmentRectRect 
{ 
    NSImage *defaultImage = [NSImage imageNamed:@"168-upload-photo-2"]; 
    NSRect ivRect = NSMakeRect(attachmentRectRect.origin.x + 5, attachmentRectRect.origin.y + 5, attachmentRectRect.size.width - 10, attachmentRectRect.size.height - 10); 
    TWIImageView *imageView = [[TWIImageView alloc] initWithFrame:ivRect]; 
    imageView.delegate = self; 
    [imageView setEditable:YES]; 
    [self addSubview:imageView]; 
    [imageView setImage:defaultImage]; 
} 

#pragma mark - 
#pragma mark TWIImageView Delegate 

// 
// mouseDown Event on TWIImageView 
// 
- (void)myImageView:(TWIImageView *)view mouseDown:(NSEvent *)event 
{ 
    NSLog(@"imageView clicked"); 
} 
#pragma mark - 

@end 

TWIImageView.h

@class TWIImageView; 
@protocol TWIImageViewDelegate <NSObject> 

- (void)myImageView:(TWIImageView *)view mouseDown:(NSEvent *)event; 

@end 

@interface TWIImageView : NSImageView 
{ 

} 

@property (assign) id<TWIImageViewDelegate> delegate; 

@end 

TWIImageView.m:

#import "TWIImageView.h" 

@implementation TWIImageView 

@synthesize delegate = _delegate; 

- (void)mouseDown:(NSEvent *)event { 
    if([self.delegate respondsToSelector:@selector(myImageView:mouseDown:)]) { 
     [self.delegate myImageView:self mouseDown:event]; 
    } 
} 

@end 

这是错误的创造,已覆盖initWithFrame方法的控制?或者是我TWIImageView失去了一些东西重要

堆栈跟踪:

Thread 1, Queue : com.apple.main-thread 
#0 0x0000000100001cd0 in -[TWIComposeWindowFrameView drawRect:] at  /Users/thomaswickl/Documents/Development/Git  Projects/QuickQuick/QuickQuick/TWIComposeWindowFrameView.m:24 
#1 0x00007fff92efa170 in -[NSView _drawRect:clip:]() 
#2 0x00007fff92ef6fe3 in -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView: ]() 
#3 0x00007fff92ef7a74 in -[NSView _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]() 
#4 0x00007fff93045fdb in -[NSNextStepFrame _recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:topView:]() 
#5 0x00007fff92ef1d9d in -[NSView _displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:]() 
#6 0x00007fff92ebbcc3 in -[NSView displayIfNeeded]() 
#7 0x00007fff93045e94 in -[NSNextStepFrame displayIfNeeded]() 
#8 0x00007fff92ebb1fc in _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints() 
#9 0x00007fff934868f1 in __83-[NSWindow _postWindowNeedsDisplayOrLayoutOrUpdateConstraintsUnlessPostingDisabled]_block_invoke_01208() 
#10 0x00007fff92b39417 in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__() 
#11 0x00007fff92b39381 in __CFRunLoopDoObservers() 
#12 0x00007fff92b147b8 in __CFRunLoopRun() 
#13 0x00007fff92b140e2 in CFRunLoopRunSpecific() 
#14 0x00007fff90ce8eb4 in RunCurrentEventLoopInMode() 
#15 0x00007fff90ce8b94 in ReceiveNextEventCommon() 
#16 0x00007fff90ce8ae3 in BlockUntilNextEventMatchingListInMode() 
#17 0x00007fff92eb8563 in _DPSNextEvent() 
#18 0x00007fff92eb7e22 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]() 
#19 0x00007fff92eaf1d3 in -[NSApplication run]() 
#20 0x00007fff92e53c06 in NSApplicationMain() 
#21 0x0000000100001242 in main at /Users/thomaswickl/Documents/Development/Git Projects/QuickQuick/QuickQuick/main.m:13 
#22 0x00007fff955db7e1 in start() 
+0

坦白说,我没有看到环。如果有人不能在drawRect的开头设置一个断点:并继续几次,然后查看调用堆栈,调用哪个方法实际上会一次又一次地调用drawRect? – 2013-03-18 15:14:48

+1

您可能会考虑在'-drawRect:'过程中保存和恢复图形上下文。我不知道它会解决你的循环问题,但它可能会解决一些问题。 – gaige 2013-03-18 15:20:02

+0

我看不到这个代码中的循环问题。我认为它发生在其他地方...只是看看你是否总是调用setNeedDisplay(在循环中)! – 2013-03-18 15:28:41

回答

0

储蓄与drawRect方法恢复图形上下文来解决问题。

1

我不认为这个答案将解决您的问题。但是,init方法可能会返回与self不同的对象。所以你最好这样做:

if (!(self = [super initWithFrame:rect])) 
    return nil; 
+0

谢谢,我改变了我的实现。 – CaptnCrash 2013-03-18 15:40:06

0

添加

[超级的drawRect:RECT];

中的drawRect方法