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

iOS 17下UIBarButtonItem的pulse符号动画失效问题(不使用UIImageView)

解决UIBarButtonItem符号动画不生效的问题

你的代码逻辑本身没问题,但符号动画的添加时机不对——在viewDidLoad阶段,UIBarButtonItem尚未被添加到实际视图层级中,此时调用addSymbolEffect不会触发动画效果。WWDC视频的描述没错,但未强调这个关键的时机细节。

修正方案:调整动画添加时机

把添加符号动画的代码移到按钮完成视图渲染之后执行,有两种可行方式:

方式1:在viewDidAppear中添加动画

import UIKit

class ViewController: UIViewController {
    private var resumeButton: UIBarButtonItem?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let config = UIImage.SymbolConfiguration(scale: UIImage.SymbolScale.large)
        let image = UIImage(systemName: "playpause.fill", withConfiguration: config)
        
        resumeButton = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(sayHello))
        toolbarItems = [resumeButton!]
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        resumeButton?.addSymbolEffect(.pulse, options: .repeating, animated: true)
        resumeButton?.isSymbolAnimationEnabled = true
    }
    
    @objc func sayHello(_ sender: UIBarButtonItem) {
        print("Hello: \(sender)")
    }
}

方式2:在viewDidLoad中延迟执行动画

通过DispatchQueue.main.async把动画代码推迟到下一次主循环,确保按钮已加入视图层级:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let config = UIImage.SymbolConfiguration(scale: UIImage.SymbolScale.large)
    let image = UIImage(systemName: "playpause.fill", withConfiguration: config)
    
    let resumeButton = UIBarButtonItem(image: image, style: .plain, target: self, action: #selector(sayHello))
    toolbarItems = [resumeButton]
    
    // 延迟执行,确保按钮完成渲染
    DispatchQueue.main.async {
        resumeButton.addSymbolEffect(.pulse, options: .repeating, animated: true)
        resumeButton.isSymbolAnimationEnabled = true
    }
}

关于自定义UIImageView的对齐问题

如果你想通过自定义视图实现动画,别直接用UIImageView作为customView,改用UIButton包裹UIImageView——UIButton会自动适配工具栏的布局规则,解决尺寸和对齐异常的问题:

override func viewDidLoad() {
    super.viewDidLoad()
    
    let config = UIImage.SymbolConfiguration(scale: UIImage.SymbolScale.large)
    let image = UIImage(systemName: "playpause.fill", withConfiguration: config)
    
    // 用UIButton包裹UIImageView,自动适配工具栏布局
    let button = UIButton(type: .system)
    button.setImage(image, for: .normal)
    button.addTarget(self, action: #selector(sayHello), for: .touchUpInside)
    
    // 给内部的UIImageView添加符号动画
    if let imageView = button.imageView {
        imageView.addSymbolEffect(.pulse, options: .repeating, animated: true)
    }
    
    let resumeButton = UIBarButtonItem(customView: button)
    toolbarItems = [resumeButton]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 22:53:32