You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

设置UITextField.isSecureTextEntry致APP内存崩溃求助

问题根源与解决办法

嘿,我之前碰到过几乎一模一样的问题!你的APP冻结崩溃的核心原因是**layoutSubviews方法陷入了无限递归循环**,而isSecureTextEntry = true的场景刚好触发了这个循环的爆发。

为什么会这样?

咱们拆解一下触发链:

  1. 当你设置密码框为安全输入模式,按下回车调用resignFirstResponder()时,UITextField的内部状态和布局会发生额外变化(比如安全文本的视觉切换、输入状态重置),这会触发系统调用layoutSubviews。
  2. 你的Textfield子类在layoutSubviews里调用了setupTextfield(),而这个方法里直接修改了self.frame.size.height = self.height——修改视图的frame会再次触发系统调用layoutSubviews,形成无限递归。
  3. 内存会在这个无限循环里被疯狂消耗,直到系统因为内存不足终止APP;而isSecureTextEntry = false时,回车收起键盘的过程中没有触发额外的布局更新,所以循环没被激活,看起来一切正常。

解决办法:停止在layoutSubviews里修改frame

layoutSubviews是系统用来通知视图更新布局的回调,绝对不能在这个方法里修改视图的frame、bounds或者触发布局变化的属性,否则必然会引发循环。我们可以把布局相关的初始化移到初始化方法里,改用Auto Layout或者仅在初始化时设置frame:

方案1:移到初始化方法(适配代码创建场景)

修改你的Textfield子类,把高度设置和初始化逻辑放到统一的初始化方法里:

@IBDesignable class Textfield: UITextField {
    let padding: UIEdgeInsets = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15)
    let height: CGFloat = 60
    let cornerRadius: CGFloat = 15
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    
    private func commonInit() {
        // 初始化时设置高度,只执行一次
        self.frame.size.height = self.height
        // 初始化样式和其他配置
        setupTextfield()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        // 这里只做需要实时响应布局变化的操作,比如根据编辑状态切换背景色
        self.backgroundColor = isEditing ? Constants.Colors.light_white : Constants.Colors.light_grey
        // 其他需要在布局更新时同步的样式也可以加在这里,但绝对不要修改frame!
    }
    
    private func setupTextfield() {
        // style
        self.styleTextfield()
        // correction
        self.autocorrectionType = .no
    }
    
    private func styleTextfield() {
        // font
        self.font = UIFont.systemFont(ofSize: 17)
        // color
        self.textColor = Constants.Colors.dark_blue.withAlphaComponent(0.6)
        // alignment
        self.contentVerticalAlignment = .center
        // default background
        self.backgroundColor = isEditing ? Constants.Colors.light_white : Constants.Colors.light_grey
        // border
        self.borderStyle = .none
        // corners
        self.layer.cornerRadius = self.cornerRadius
        // shadow
        self.layer.shadowColor = UIColor.black.cgColor
        self.layer.shadowOpacity = 0.1
        self.layer.shadowOffset = CGSize(width: 0, height: 3)
    }
    
    // 其他重写方法保持不变...
}

方案2:用Auto Layout约束高度(更推荐,适配Storyboard/XIB场景)

如果你是用Storyboard或者XIB创建的文本框,更推荐用Auto Layout来固定高度,避免直接修改frame:

private func commonInit() {
    // 关闭自动转换约束,手动添加约束
    translatesAutoresizingMaskIntoConstraints = false
    // 添加高度约束
    NSLayoutConstraint.activate([
        self.heightAnchor.constraint(equalToConstant: height)
    ])
    setupTextfield()
}

这样修改后,按下回车收起键盘时,layoutSubviews只会执行必要的布局更新,不会触发无限循环,内存问题就彻底解决了。

内容的提问来源于stack exchange,提问作者Lukas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:28:14