首页 > 趣闻 > 正文内容

Swift开发:重写父类方法的3个关键步骤与注意事项

趣闻2025-05-28 07:53:41

(场景导入)当你给UIButton添加点击波纹动画时,发现系统自带的点击反馈突然消失;当你在UITableViewCell里自定义选中样式,却导致整个列表滑动卡顿...这些糟心问题的根源,可能都出在方法重写这个基础操作上。

今天咱们就聊聊这个让无数Swift新手踩坑的技术点。上周帮实习生排查bug,发现他重写UIControl的sendAction方法时,漏掉了super调用,直接导致按钮事件传递链断裂——这种错误就像炒菜忘放盐,看着菜熟了,吃进嘴里才发现不对劲。

??关键步骤一:确认战场(方法可重写性)??
打开Xcode随便建个自定义View试试:

swift复制
class ParentClass {
    fileprivate func secretMethod() { }  // 这个你重写不了
    open func publicMethod() { }  // 这个可以随便改
}

class ChildClass: ParentClass {
    // override func secretMethod() { }  // 编译器直接报红
    override func publicMethod() {
        super.publicMethod()  // 先让父类干完活
        // 你的定制代码
    }
}

这里有个冷知识:Swift要求父类方法必须用open或public修饰才能被重写,这点和Objective-C完全不同。之前有学员在自定义UINavigationBar时,死活重写不了layoutSubviews方法,最后发现是权限修饰符搞的鬼。

??关键步骤二:战术部署(override操作规范)??
看个真实案例。上周看到有人这样重写UIViewController的生命周期:

swift复制
override func viewWillAppear(_ animated: Bool) {
    // 忘记写super.viewWillAppear(animated)
    trackPageView()  // 埋点代码
}

结果页面跳转时出现诡异的导航栏闪烁。这是因为在iOS系统里,像viewWillAppear这样的生命周期方法,父类实现里藏着界面渲染的关键逻辑。这就好比拆炸弹时剪错电线,虽然看起来程序能跑,但隐患随时会爆。

??关键步骤三:战后清理(super调用策略)??
什么时候必须调super?什么时候可以不调?这张对照表说清楚:

方法类型super调用必要性典型例子
生命周期方法必须调用viewDidLoad/viewWillAppear
空实现方法可不调用UIResponder的touches系列
数据源/代理方法禁止调用tableView(_:cellForRowAt:)

去年有个项目因为误调super.tableView(_:cellForRowAt:)导致复用池混乱,直接让列表滚动FPS降到40以下。这种性能问题就像温水煮青蛙,等到用户投诉才发现就晚了。

(高频问题自问自答)
Q:为什么我重写的方法没被调用?
A:先做三个检查:1.继承关系是否正确 2.方法签名是否完全一致 3.父类方法权限是否为open/public。上周遇到个奇葩案例,有人把参数名从animated改成isAnimated,结果方法直接不执行。

Q:重写init方法要注意什么?
A:记住这个保命公式:

swift复制
convenience init() {
    self.init(frame: .zero)
    // 后续初始化
}

override init(frame: CGRect) {
    super.init(frame: frame)
    // 你的配置
}

@available(*, unavailable)
required init?(coder: NSCoder) {
    fatalError("不支持故事板")
}

这套组合拳能避免99%的初始化崩溃问题,特别是处理UIView子类时。

小编观点:方法重写就像玩跷跷板,要在系统行为和自定义需求之间找平衡点。建议新手养成两个习惯:1.重写方法前CMD+点击查看父类实现 2.在override后面先写super调用再写自己的代码。记住,编译器报错不是敌人,而是防止你翻车的安全员。

搜索