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

标签 ios objective-c cocoa-touch uiview

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

  • 子类化 UIView --> 我们称它为 Grapher
  • 在其中实现我所有的方法(drawBarGraphdrawProgressBardrawLineGraph)
  • 将其包含在所需的 View Controller 中,创建 Grapher 的实例,调用所需的方法
  • 将该实例作为 subview 添加到我的主视图。

让我们进入一些代码,因为我不确定如何解释它。这是 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),覆盖 drawRect在那里,alloc-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。如何在当前上下文中传递?我做错了什么以及如何解决这个问题?
如果我解释得太草率,请告诉我,我会更加努力。

干杯,一月

最佳答案

What am I doing wrong and how to fix this?

如果我没理解错的话,你误解了 View 的作用。

View 在自己的空间中管理自己的绘图。你不给它一个上下文,你让它根据需要创建或设置一个上下文并在它自己的坐标系中绘制。听起来您正在尝试创建一个在另一个 View 的上下文中绘制的 View ,我想不出这样做的一个很好的理由。来自 UIView 的文档,就在页面顶部:

The UIView class defines a rectangular area on the screen and the interfaces for managing the content in that area. At runtime, a view object handles the rendering of any content in its area and also handles any interactions with that content.

如果您试图创建一个仅在另一个 View 中绘制某些内容的 View ,那您就错了。将绘图方法封装在某个类中并使用该类的实例在 View 中绘制图形可能没问题,但如果这是您想要的,则不应将该类设为 UIView 的子类。

If I subclass it as a NSObject then subclass UIView in another file (lets call it GraphArea), override drawRect there, alloc-init the Grapher and pass the UIGraphicsGetCurrentContext() in it works just fine.

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

关于ios - 用于自定义绘图的子类 UIView,上下文为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18083430/

相关文章:

ios - 使用 kSecAttrAccessible 将 RSA 公钥存储到 iOS 钥匙串(keychain)中

ios - 使用 RxSwift 将 UITableViewCell 中的控件绑定(bind)到 ViewModel 的最佳实践

ios - 如何创建免费的应用内购买?

ios - 如何从Objective-C中的UUID获取特性?

ios - UIView 当它是 tableHeaderView 时更新,但当它是 subview 时不更新

ios - 带有按钮的弹出框/工具提示,就像 iOS 自动更正一样

ios - 如何根据 iPhone 型号显示 View

ios - 使用未声明的类型 'Player'

ios - 尝试在 iPhone 上以模态方式呈现 UIImagePickerController 时崩溃

iphone - UITableView 未正确对齐