【问题标题】:Can't get setNeedsDisplay not working with my custom view to show changes无法让 setNeedsDisplay 无法使用我的自定义视图来显示更改
【发布时间】:2012-04-07 01:58:55
【问题描述】:

我正在尝试在自定义视图 (rectView) 中创建一个 CGRect,它会在您移动滑块时上下移动。

我的滑块的 IBAction 调用了以下方法:(这很好)

- (void)moveRectUpOrDown:(int)y
{
    self.verticalPositionOfRect += y;
    [self setNeedsDisplay];
}

我的drawRect方法:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGFloat size = 100;
    self.rect = CGRectMake((self.bounds.size.width / 2) - (size / 2), 
                                 self.verticalPositionOfRect - (size / 2), 
                                 size, 
                                 size);
    CGContextAddRect(context, self.rect);
    CGContextFillPath(context);
}

我的自定义视图的 initWithFrame 使用 setNeedsDisplay 调用 drawRect 方法,但由于某种原因 moveRectUpOrDown 不会调用 drawRect。

任何想法我做错了什么?

为清楚起见,整个实现如下:

//ViewController.h
#import <UIKit/UIKit.h>
#import "rectView.h"

@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet rectView *rectView;
- (IBAction)sliderChanged:(id)sender;
@end

//ViewController.m
#import "ViewController.h"

@implementation ViewController
@synthesize rectView;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.rectView = [[rectView alloc] initWithFrame:self.rectView.frame];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (IBAction)sliderChanged:(id)sender 
{
    UISlider *slider = sender;
    CGFloat sliderValue = slider.value;
    [self.rectView moveRectUpOrDown:sliderValue];
}
@end

//rectView.h
#import <UIKit/UIKit.h>

@interface rectView : UIView
- (void)moveRectUpOrDown:(int)y;
@end

//rectView.m
#import "rectView.h"

@interface rectView ()
@property CGRect rect;
@property int verticalPositionOfRect;
@end

@implementation rectView
@synthesize rect, verticalPositionOfRect;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {

        self.verticalPositionOfRect = (self.bounds.size.height / 2);
        [self setNeedsDisplay];
    }
    return self;
}

- (void)moveRectUpOrDown:(int)y
{
    self.verticalPositionOfRect += y;
    [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGFloat size = 100.0;
    self.rect = CGRectMake((self.bounds.size.width / 2) - (size / 2), 
                                 self.verticalPositionOfRect - (size / 2), 
                                 size, 
                                 size);
    CGContextAddRect(context, self.rect);
    CGContextFillPath(context);
}

@end

感谢您的帮助:)

【问题讨论】:

  • 我想只添加一个CALayer 并对其进行上下动画处理会比一直重绘更有效
  • 还没有调查过,但我现在会调查一下。我基本上这样做是为了让我了解 Quartz 的基础知识
  • 所以您已经确认-drawRect: 没有被调用?还是叫不画?
  • 它根本没有被调用,我在里面放了一个 NSLog 来测试。 drawRect 仅在视图 initWithFrame 中被调用一次,但在更改滑块的值时不会被调用(从滑块的 IBAction 调用 setNeedsDisplay is)但它不会调用 drawRect?
  • self 是实际的视图吗?或父母。也许试试[self.myView setNeedsDisplay]

标签: iphone ios cocoa quartz-graphics


【解决方案1】:

好的,所以答案是视图实际上从未添加到viewController 的视图中。..

你有一个IBOutlet 到你的rectView - 所以我假设你在Interface Builder 中将一个UIView 组件拖到view 上,然后将它的类更改为rectView,这一切都很好但是viewDidLoad中,你用一个新的对象擦掉了这个对象

self.rectView = [[rectView alloc] initWithFrame:self.rectView.frame];

所以这现在不再是从 xib 加载的对象了。

随后,该视图从未真正添加到视图层次结构中,因此它永远不会自行绘制,因为它没有意义。

所以解决方案是删除我上面突出显示的行。


注意事项

对于这样的实现,我可能仍会选择我的其他答案,但它有助于绊倒并学习新事物。

rectView 不遵循命名约定。理想情况下,您的班级名称应以 2-3 个字母前缀(可能是您的首字母或公司名称)开头,后跟一个驼峰式命名。

【讨论】:

  • 我也同意你的另一个想法是一个更好的实现:)
【解决方案2】:

我看不到您如何初始化 CGFloat 大小。你能在里面放一个值,看看它是如何工作的吗?其余的代码在我看来没问题。

【讨论】:

  • 那个,你可能想设置填充颜色。顺便说一句,使用 UIBezierPath 进行简单绘图总是比使用 Core Graphics 的全部功能更容易。
  • 抱歉,这只是一个错字,实际上并没有出现在我的代码中,我现在修复了它。但问题仍然存在。
【解决方案3】:

更简单的方法是添加 UIView 并为其设置动画。

为此UIView添加一个ivar

// .h
@property (nonatomic, strong) UIView *animatedView;

// .m
@synthesize animatedView = _animatedView;

然后用这个替换你的逻辑

- (void)moveRectUpOrDown:(int)y;
{
    CGRect frame = self.animatedView.frame;
    frame.origin.y += y;

    // If you want the change to animate uncomment this
    // [UIView animateWithDuration:0.25f
    //                  animations:^{
    //                      self.animatedView.frame = frame;
    //                  }];

    // If you don't want the change to animate uncomment this
    // self.animatedView.frame = frame;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-30
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多