ios - 是什么导致了 <Error> : CGContextSetBaseCTM: invalid context 0x0 when implementing loadView?

标签 ios objective-c uiview uiviewcontroller

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

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

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

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

如果您改为调用 [super loadView],则不会发生这种情况。

为什么?

最佳答案

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

我有。不过,OS X 上的 Apple 应用程序也会向控制台发出相同的消息,因此,如果它是由 Apple 框架代码发出的,除了提交错误外,你可能无能为力。

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

因此,在尝试执行任何需要有效 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];
}

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

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

您绝对可以在 initWithFrame: 中将 CGZeroRect 设置为您的框架,并且您应该使用自动布局。 你绝对仍然可以改用 init,尽管没有记录,只要你在任何东西到达你的 CGContext 之前设置一个框架或添加约束。 它没有记录,所以它是有风险的。 你应该总是使用 initWithFrame: 如果你没有使用 xib/nib/storyboard(那些将从 initWithCoder: 中的 xib/nib/storyboard 获取框架)

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

关于ios - 是什么导致了 <Error> : CGContextSetBaseCTM: invalid context 0x0 when implementing loadView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22874036/

相关文章:

ios - 物理世界.bodyAlongRayStart()创建幻影println(读取 'Chance')-覆盖println函数?

ios - UIView animateWithDuration 等到动画结束

iphone - 日期选择器是否可以显示年/月/日 + 日名称?

objective-c - 退出全屏模式后如何接收 NSView 的键盘事件?

uiview - 在 Swift3 中,KVO 是 UIView 的 alpha 吗?

iphone - CoreData 对多对多关系排序

ios - IOS中如何去除UILabel中多余的空格

ios - 画一条线连接两个圆

iphone - 当 UISlider 成为 UIView 其他 self.view 的 subview 时,它不会工作

ios - ipad 和 iphone 的自适应大小类解决方案