用于自定义绘图的子类UIView,上下文为null

时间:2013-08-06 14:47:22

标签: ios objective-c cocoa-touch uiview

我想有一个用于在其中呈现简单图表的类(没有复杂的东西)。我的想法是:

  • 子类UIView - >我们称之为Grapher
  • 在其中实施我的所有方法(drawBarGraphdrawProgressBardrawLineGraph
  • 将其包含在所需的视图控制器中,创建Grapher的实例,调用所需的方法
  • 将该实例作为子视图添加到我的主视图中。

让我们跳进一些代码,因为我不知道如何解释这个。这是grapher.h

@interface Grapher : UIView
{
    CGContextRef context; //for passing it in via constructor

    //UIColor *backgroundColor;
    UIColor *graphColor; //foreground color
}

- (id)initWithFrame:(CGRect)frm inContext:(CGContextRef)ctx;

- (void)setGraphColor:(UIColor*)color;

- (void)drawHistogramWithItems:(NSArray*)items;
//- (void)drawLineChartWithItems:(NSArray*)items;
- (void)drawProgressLineWithPercentage:(float)percent;

以及相应的grapher.m

@implementation Grapher

- (id)initWithFrame:(CGRect)frm inContext:(CGContextRef)ctx
{
    self = [super initWithFrame:frm];
    if (self)
    {
        context = ctx;
    }
    return self;
}

#pragma Mark main draw methods

- (void)drawHistogramWithItems:(NSArray *)items
{
    //[backgroundColor set];
    //UIRectFill(frame);
    [graphColor set];

    int itemWidth = 20;

    if (items.count == 0) return;

    float max = -1;
    for (SFGraphItem *item in items)
        if (item.value > max)
            max = item.value;

    float spacing = (frame.size.width - (itemWidth * items.count)) / (items.count + 1);
    float xPos = spacing;

    for (int i = 0; i < items.count; i++)
    {
        CGFloat itemHeight = ((SFGraphItem*)[items objectAtIndex:i]).value / max * frame.size.height;
        CGRect bar = CGRectMake(xPos, frame.origin.y + frame.size.height - itemHeight, itemWidth, itemHeight);
        CGContextAddRect(context, bar);
        CGContextDrawPath(context, kCGPathFill);
        xPos += spacing + itemWidth;
    }

}

- (void)drawProgressLineWithPercentage:(float)percent
{
    //[backgroundColor set];
    //UIRectFill(frame);
    [graphColor set];
    UIRectFill(CGRectMake(frame.origin.x, frame.origin.y, frame.size.width / 100 * percent, frame.size.height));
}

#pragma Mark setters/getters

- (void)setGraphColor:(UIColor *)color
{
    graphColor = color;
}

@end

美好而简单。如果我将其子类化为NSObject,则将子类UIView子类化为另一个文件(让我们称之为GraphArea),在那里覆盖drawRectalloc-init Grapher并且传递UIGraphicsGetCurrentContext()就可以了。

但我不想要这个“中间观点”。我想将UIView作为Grapher继承,并按照以下方式进行:

Grapher *graph = [[Grapher alloc] initWithFrame:CGRectMake(5, 65, winSize.width - 10, 20)]; //some random frame
[graph setGraphColor:[UIColor redColor]];
[graph drawProgressLineWithPercentage:50];
graph.backgroundColor = [UIColor grayColor];

[someview addSubview:graph];

如果我用CGContextRef或者这个构造函数调用构造函数并尝试获取上下文,则它始终为null。如何传递当前的背景?我做错了什么以及如何解决这个问题? 如果我解释它太草率让我知道,我会更加努力。

干杯,Jan。

1 个答案:

答案 0 :(得分:2)

  

我做错了什么以及如何解决这个问题?

如果我理解正确,你会误解观点的作用。

视图在自己的空间中管理自己的绘图。您没有给它一个上下文,您可以根据需要创建或设置上下文并在其自己的坐标系中绘制。听起来你正在尝试创建一个吸引另一个视图的上下文的视图,而我无法想到这样做的一个好理由。从UIView的文档中,在页面顶部的那边:

  

UIView类在屏幕上定义了一个矩形区域   用于管理该区域内容的界面。在运行时,一个视图   object处理其区域中任何内容的呈现   处理与该内容的任何互动。

如果您正在尝试创建一个只在另一个视图中绘制内容的视图,那么您做错了。将绘图方法封装在某个类中并使用该类的实例在视图中绘制图形可能会很好,但如果这是您想要的,则不应将该类作为UIView的子类。

  

如果我将其子类化为NSObject,则将UIView子类化为另一个文件   (我们称之为GraphArea),在那里覆盖drawRect,alloc-init   Grapher并传递UIGraphicsGetCurrentContext()就可以了   细

继承UIView很好,但是UIView子类尝试在其他视图的空间中绘制也不行。如果您想创建一个可以作为内容添加到其他视图的图形,但不想使图形成为自己的视图,那么您可能会查看CALayer。使用图层,您可以覆盖-drawInContext:来进行绘图。您可以创建图层并将其添加到现有视图中。绘图系统将您的图层与视图的其他图层合成。