Swift UILabel如何成为CALayer并导致崩溃?
我有一个自定义的Swift UILabel如何成为CALayer并导致崩溃?,swift,memory-management,ios9,Swift,Memory Management,Ios9,我有一个自定义的UIView,其中几个实例是在一个循环中创建的: let models = CDMyModel.MR_findAllSortedBy("position", ascending: true) as! [CDMyModel] for view in myViews { view.removeFromSuperview() } self.myViews.removeAll(keepCapacity: true) for model in models { let
UIView
,其中几个实例是在一个循环中创建的:
let models = CDMyModel.MR_findAllSortedBy("position", ascending: true) as! [CDMyModel]
for view in myViews {
view.removeFromSuperview()
}
self.myViews.removeAll(keepCapacity: true)
for model in models {
let myView = MYFaqView(width: CGRectGetWidth(self.view.frame))
myView.titleLabel.text = model.title
myView.content.text = model.content
myView.titleLabel.sizeToFit()
self.scrollView.addSubview(myView)
self.myViews.append(myView)
}
我确实有时会看到Crashlytics中的崩溃与myView.content.text=model.content
:
根据这次崩溃,我认为它与内存有关,但我真的不知道myView是如何在那时发布的
所有这些都会在视图中出现:
。之前的移除可能与此有关吗?但是我假设所有的事情都发生在主线程上,所以这也不应该是个问题——我真的被困在这里了
崩溃发生在iOS 9上
编辑
let content:UILabel = {
let l = UILabel()
l.numberOfLines = 0
if let font = UIFont(name: "OpenSans", size: 14) {
l.font = font
}
return l
}()
MyFaqView初始化方法:
init(width:CGFloat) {
self.width = width
super.init(frame: CGRectZero)
self.addSubview(self.titleLabel)
self.addSubview(self.toggleImageView)
self.addSubview(self.separatorView)
self.content.clipsToBounds = true
self.addSubview(self.content)
self.translatesAutoresizingMaskIntoConstraints = false
self.clipsToBounds = true
}
编辑
let content:UILabel = {
let l = UILabel()
l.numberOfLines = 0
if let font = UIFont(name: "OpenSans", size: 14) {
l.font = font
}
return l
}()
简要查看显示了两个潜在问题:
removeFromSuperview()
真正从层次结构中删除视图并释放它,减少MyView中的元素数量这些问题总是很难找到 基本上,正在发生的是内存损坏。先前由
UILabel
内容占用的地址0x14f822a0
已被其他内容使用,在本例中为CALayer
。如果本地发生崩溃,您可以通过在lldb中输入po 0x14f822a0
来验证这一点,并确保它将输出CALayer
类型的地址
对于这些错误,虽然碰撞线可以提供线索,但它并不总是错误的原因。其他地方已经发生了一些事情
尽管Swift主要是内存管理的,但对于粗心的人来说仍然存在陷阱。就我个人而言,我已经看到了导致记忆衰退的两个主要原因。第一个是由自引用闭包引起的保留循环。第二个与您的问题更相关的是与故事板和XIB相关的视图
如果我们遵循逻辑,我们可以认为
崩溃EXC\u BAD\u指令
UILabel
内容的原始居民。那么为什么运行时会发布内容呢?因为它不再是必需的,也就是说,它不是它仍然需要的任何视图的子视图或属性
我敢打赌,如果您将content更改为一个子类UILabel
,并添加一个deinit
方法,然后将其作为断点,您将惊讶地看到它在早期被意外地反初始化。要测试此属性,请创建一个类型,如下所示:
class DebugLabel: UILabel
{
func deinit
{
NSLog("Breakpoint on this line here!")
}
}
然后将内容的类型更改为上面的调试标签
那么,为什么会发生这一切?我的钱花在你有一个视图属性上,它是通过编程方式创建的,要么是弱的
,要么是无主的
。也许您以前使用IBOutlet
设置了这些,然后您删除了它,但忘记删除weak
指示符
仔细检查每一个问题,我相信您会找到上述问题的原因。使用初始化器或
UINib
以编程方式创建的任何内容都不应指定为weak
或unowned
您是否可以包含MYFaqView
的init方法的源代码?显示内容视图/标签的初始化?使用Zombies工具在Instruments下运行。它找到僵尸了吗?myViews
是我在updateViewConstraints
中需要的所有视图的数组,所以removeAll
实际上并没有将它们从视图层次结构中移除-我想这没有问题,对吧?为什么不只使用scrollView.subview呢?试着从MyView中删除依赖项,看看会发生什么问题是它不会经常崩溃,对大多数用户来说它不会崩溃-我无法一次重现它,但在crashlytics中,我看到在那个地方有多个崩溃,所以我不知道我是否解决了这个问题MYFaqView init里面有什么?@MaratAl永远不要使用scrollView.subview
。它包含滚动视图指示器,即使这些指示器是隐藏的,你也不应该弄乱它们。