NSLayoutConstraint VFL 因为 EXC_BAD_ACCESS 而崩溃

Posted

技术标签:

【中文标题】NSLayoutConstraint VFL 因为 EXC_BAD_ACCESS 而崩溃【英文标题】:NSLayoutConstraint VFL crashes because of EXC_BAD_ACCESS 【发布时间】:2016-10-25 15:59:41 【问题描述】:

我正在开发的应用程序有很多视觉格式约束。在一次操作中收集了一些网络请求后,我开始遇到 EXC_BAD_ACCESS 崩溃。如果我通过 NSLayoutConstraint(item.... ) 初始化程序手动创建约束,我不会遇到任何崩溃。

这是我的代码中发生崩溃的行:

这是崩溃日志:

什么可能导致此崩溃?以及如何解决?

【问题讨论】:

这基本上看起来不错(请参阅下面不相关的警告)。这个对我有用。你在哪里叫这个addConstraints?显然,它必须在UIView 子类中,但是您究竟在哪里做呢?最重要的是,我们需要一个MCVE。根据您在此处提供的内容,我无法重现该问题。 无关的,一般你会说options: []NSLayoutFormatOptionsOptionSet,而空集只是 []。实际上,使用constraints 方法,options 参数是可选的,默认为[],因此您甚至可以完全省略options: [] 【参考方案1】:

我在创建 NSLayoutConstraints 数组然后从数组中一次性激活时遇到了同样的问题。

当您导航到远离视图然后返回到该视图时,有时视图可能会分配到不同的内存分配并导致错误访问错误。

这就是发生的事情。每次加载视图时都会将新约束添加到数组中(假设您添加它们并从 .viewDidLoad() 函数或从每次视图再次可见时加载的类似函数激活它们)。

当您离开数组时,数组不会自行清空,因此旧约束也保留在数组中。当您导航回视图并尝试激活约束时,系统会尝试再次激活旧的约束(它们引用的内存不包含您的约束所引用的任何视图)。

要解决此问题,请在向其添加新约束之前在您的数组上调用 .RemoveAll()。这将确保所有旧的约束都被移除并且系统不会尝试激活它们。

这是一个例子。

var initialConstraints = [NSLayoutConstraint]()

    override func viewDidLoad() 
    super.viewDidLoad()

    // Empty the array once the view loads
    initialConstraints.removeAll()

    // Add your constraints like normal
    initialConstraints.append(...)

    // Activate your constraints once you've added them to the array (like normal)
    NSLayoutConstraint.activate(initialConstraints)


希望这会有所帮助!

【讨论】:

视图如何多次加载自身? 对不起,我忘了提及 - 当我从一个标签导航到另一个标签然后返回原始标签时发生这种情况。 但是在标签之间导航不应该触发 viewDidLoad 除非你是故意调用它们 在我的应用程序中,在 viewDidLoad 中放置一个断点表明每次我导航到选项卡时都会调用它,并且我没有在我自己的代码中调用 .viewDidLoad 函数。你最终是如何解决这个问题的? 我无法解决我必须使用 NSLayoutContraint.init 方法构造所有 Visual 格式的约束

以上是关于NSLayoutConstraint VFL 因为 EXC_BAD_ACCESS 而崩溃的主要内容,如果未能解决你的问题,请参考以下文章

Autolayout开发之VFL语句

使用Auto Layout中的VFL(Visual format language)--代码实现自动布局转

iOS代码约束处理&&Masonry源码分析

VFL语言

AutoLayout - VFL

iOS学习之VFL语言简介