Swift中如何在函数返回指定返回码时禁用按钮并修复Xcode报错
报错原因
你遇到的编译报错和业务逻辑无关,是因为你把控制按钮状态、while循环这几行执行代码直接写在了类的顶层作用域,Swift中类的顶层只能放属性、方法的声明代码,不能直接写执行语句,编译器会误把这几行代码识别为连续的声明语句,因此抛出需要分号分隔的错误。
你只要把这部分代码放到任意方法内部(比如viewDidLoad、某个触发检查的动作方法里),就能直接消除这个编译报错。
原有逻辑的问题
即便解决了编译问题,你的原有逻辑也无法正常运行:while死循环会直接阻塞主线程,macOS所有UI刷新、用户交互都依赖主线程调度,阻塞后会直接导致整个APP无响应,按钮禁用的状态也不会正常生效,甚至系统会直接杀掉卡死的APP。
正确实现方案
根据你的实际使用场景选择对应方案:
场景1:check()的返回值由你本地业务逻辑控制,状态变化时机可知
你可以单独封装按钮状态更新方法,在所有会改变check()返回值的业务逻辑位置主动调用即可,性能最高:
func updateMyBtnEnableStatus() { mybtn.isEnabled = check() != 30 }
场景2:check()的返回值变化不可预知,需要轮询检测
不要用死循环,改用定时器定时检测状态,不会阻塞主线程:
首先在类中声明定时器存储属性:
var statusCheckTimer: Timer?
在需要开始检测的位置(比如页面加载完成后)启动定时器:
// 每100ms检测一次状态,可根据需求调整间隔 statusCheckTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { [weak self] _ in guard let self = self else { return } self.mybtn.isEnabled = self.check() != 30 }
在不需要检测的时机销毁定时器避免内存泄漏:
statusCheckTimer?.invalidate() statusCheckTimer = nil
场景3:需要阻塞当前业务流程直到check()返回非30再继续
如果确实需要等待状态恢复后再执行后续逻辑,把轮询逻辑放到后台线程执行,完成后切回主线程更新UI和执行业务:
// 先在主线程禁用按钮 mybtn.isEnabled = false // 切换到后台线程轮询,避免阻塞主线程 DispatchQueue.global().async { [weak self] in guard let self = self else { return } while self.check() == 30 { print("Invalid, don't break this while loop") // 增加休眠降低CPU占用 Thread.sleep(forTimeInterval: 0.1) } // UI操作必须切回主线程 DispatchQueue.main.async { self.mybtn.isEnabled = true // 此处写后续要执行的业务逻辑 } }
内容的提问来源于stack exchange,提问作者functionendsherelmao
相关产品推荐
相关产品推荐

