导致<error>的原因:CGContextSetBaseCTM:实现loadView时无效的上下文0x0 </error>

时间:2014-04-04 22:25:56

标签: ios objective-c uiview uiviewcontroller

我有一个在loadView中执行此操作的ViewController:

self.view = [[UIView alloc] init];

有时这会导致控制台出现以下错误:

:CGContextSetBaseCTM:无效的上下文0x0。这是一个严重的错误。该应用程序或其使用的库正在使用无效的上下文,从而导致系统稳定性和可靠性的整体降低。此通知是礼貌的:请解决此问题。在即将到来的更新中,它将成为一个致命的错误。

如果您拨打[super loadView],则不会发生这种情况。

为什么?

2 个答案:

答案 0 :(得分:5)

如果您在拥有图形上下文之前尝试对图形上下文执行操作,则会发生这种情况。 您可以在OS X上看到相同的内容。 确保您的视图实际位于窗口中的视图层次结构中。 Core Graphics / Quartz,没有窗口就没有给你一个图形上下文。 在iOS上有一个窗口。 UIView的子类可以使用viewDidMoveToWindow或viewDidMoveToSuperview来检查窗口是否为零并且superview不是nil。 这告诉你应该有可能得到一个有效的上下文。 NSView也有类似的方法可以覆盖。

我&#39;已经。在OS X上看到的Apple应用程序也会向控制台发送相同的消息,因此如果它由Apple框架代码发出,除非提交错误,否则您可能无法解决任何问题。

在这种情况下,init会给你一个UIVIew,但它不是指定的初始化程序,它是initWithFrame:对于OS X上的NSView也是如此。所以你的视图没有框架,没有坐标空间。因此,在某些时候,当您没有有效的上下文时,会调用需要有效图形上下文的代码。它可能是您的代码,可能是框架代码。一些未记录的事情发生在未记录的订单中。通常,如果您使用推荐的方法并按正确的顺序执行操作,则不必担心它。

因此,在尝试执行任何需要有效CGContext的操作之前,需要设置一个frame属性。当您尝试更改CGContext时,还需要确保它具有有效的CGContext。 错误说CGContextSetCTM是一个CGContext函数,用于设置图形上下文的转换。使用CGContextGetCTM很容易做到这一点。如果传入的上下文无效,则会出现此错误。所以,问题是,这是你的代码吗?还是其他人的?

在UIViewController子类中考虑以下内容

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.aView = [[UIView alloc] init];
//  self.aView.frame = CGRectMake(0, 0, 30, 30);
// Uncomment the above line and your error will go away. Not because you set a size greater than zero, but because you set an origin point and a size for the frame.
// Set the frame after the view is in the window view hierarchy and the error will stop occurring.
    self.aView.backgroundColor = [UIColor redColor];
    [self.view addSubview:self.aView];

    CGContextRef context = UIGraphicsGetCurrentContext();
// This context is actually NULL.
    CGAffineTransform CTM = CGContextGetCTM(context);
// Above line will give you a nice similar error. (get instead of set)
    [self.view setNeedsDisplay];
}

我们不知道操作是否正在使用Autolayout。没有发布足够的代码。 如果添加可满足的NSLayoutConstraints,Autolayout系统将创建原点,因此可以创建有效的CGContext。 但问题的关键是必须在访问或修改上下文之前设置from的原点和大小,因为没有它,你有一个NULL CGContext。 使用Autolayout时,必须在访问或修改上下文之前添加约束。 对于手动布局框架,必须在访问或修改上下文之前设置框架(零矩形或其他)。

指定的初始化程序要求它的原因是因为它是最安全的时候确保在它为NULL时没有任何东西碰到CGContext。

你绝对可以在initWithFrame中将CGZeroRect设置为你的框架:你应该使用Autolayout。 只要您设置一个框架或在任何命中CGContext之前添加约束,您绝对可以使用init而不是文档。 它没有记录,所以它有风险。 你应该总是使用initWithFrame:如果你没有使用xib / nib / storyboard(那些将从initWithCoder中的xib / nib / storyboard获取帧:)

最好的建议仍然是使用指定的初始化程序,但事实是,在视图移动到有效窗口中的有效视图层次结构之前,CGContext实际上不存在,因为上下文是从父视图上下文派生的。窗口中的有效层次结构。

答案 1 :(得分:2)

我相信当视图尝试使用空边界(CGContextRef)创建CGRectZero时,可能会发生这种情况。为了确保不会发生这种情况,您应该在初始化时为视图指定框架。我通常使用

[UIView initWithFrame:[[UIScreen mainScreen] applicationFrame]];