我有一个自定义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在那时是如何发布的。
所有这些都发生在viewWillAppear:
中。之前的删除是否必须对此做些什么?但是我假设一切都发生在主线程上,所以这不应该是一个问题 - 我真的被困在这里。
崩溃发生在iOS 9上。
修改
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
}()
答案 0 :(得分:2)
这些问题总是非常难以追查。
基本上,正在发生的是内存损坏。之前由0x14f822a0
内容占据的地址UILabel
已被其他内容使用,在本例中为CALayer
。如果在本地发生崩溃,可以通过在lldb中输入po 0x14f822a0
来验证这一点,并且确定它会将该地址输出为CALayer
类型。
有了这些错误,虽然崩溃线可以提供线索,但并不总是导致错误。其他地方已经发生了一些事情。
虽然Swift主要是内存管理,但对于那些粗心大意的人来说仍然存在陷阱。我个人看到了内存损坏的两个主要原因。第一个是由自引用闭包引起的保留周期。第二个 - 与您的问题更相关 - 与Storyboards和Xibs相关的视图。
如果我们通过逻辑方式遵循此规则,我们可以认为CALayer
现在占用了UILabel
内容以前占用的地址空间。运行时尝试向对象发送消息是think占用该地址,并且由Swift运行时断言捕获,然后触发EXC_BAD_INSTRUCTION
崩溃。
现在,对于其他一些在该地址居住的对象,必须释放UILabel
内容的原始居民。那么为什么运行时会发布内容?因为它不再是必需的,即它不是任何视图的子视图或属性,它仍然是必需的。
我敢打赌,如果你将内容更改为子类UILabel
并添加一个deinit
方法然后断点,你会惊讶地发现它是意外地在早期被初始化了。要测试这个,请按如下方式创建一个类型:
class DebugLabel: UILabel
{
func deinit
{
NSLog("Breakpoint on this line here!")
}
}
然后将内容的类型更改为上面的DebugLabel
。
那为什么会发生这一切?我的钱是您的一个视图属性已经以编程方式创建为weak
或unowned
。也许您之前使用IBOutlet
设置了这些设置,然后删除但忘记删除weak
指示符?
仔细检查每一个,我相信你会找到上述问题的原因。通过使用初始化程序或UINib
以编程方式创建的任何内容都不应指定为weak
或unowned
。
答案 1 :(得分:0)
简短的观看向我展示了两个潜在的问题:
removeFromSuperview()
确实从层次结构中删除了视图并将其释放并减少了myView中的元素数量。for myViews中的视图{ view.removeFromSuperview()}
self.myViews.removeAll(keepCapacity:true)