本篇本猫向大家演示了初学者用Swift语言编码时容易掉入的2个陷阱,希望可以帮助到大家
为什么是Swift?有些时候你以为是馅饼,其实却是陷阱。
这两个陷阱之所以放在Swift语言里讲解,是因为Swift有一个超级强大的语法特性:闭包!
正式因为闭包超级强大,所以误用起来副作用也是非常了得!
那句话怎么说的?C语言误伤你一个手指头,C++会轰掉你整个手臂,那么Swift可能会把你变成人棍…
怕了吗?别急,就让本猫带领大家越过陷阱,跨越人生之巅… ?
陷阱一:今天不是今天!?编程里面,涉及时间的地方往往是Bug之源,Swift也不例外。
比如一个很简单的逻辑:判断当前日期是不是今天.
let today = Date() if someday.isSameDay(today){ // 如果是今天则做些事情... }
上面代码很美好,但下面的代码就不一定了…
static func createView(delegate:ViewDelegate)->PayloadView { let view = PayloadView() {view in let today = Date() view.swipeDelegate = delegate // 一些初始化代码 if view.payload != nil{ // 若负载不为nil,则需要在完成负载时做出处理 view.setPayloadConfirmedHandler {payload in // 取得今天的负载完成数量 let count = payload.wasCompletedAt(day: today).count if count > 5{ // 大于5时进一步处理 } } } } return view }
这是真实App中的代码,为了演示我做了简化。
大家从上面的注释中可以了解到这段不长的代码到底做了神马。
PayloadView会以列表的形式显示在App的界面中,那么上面代码有什么问题吗?
咋一看貌似没什么问题啊!
我也想说没问题,可实际那是欺骗你们的感情…
可能这个App执行500次都是正常的,可就有那么几次,你会发现,怎么这段代码取得的完全是错误的负载数量呢??
考虑一下:如果你的App在后台一直不被杀掉,直到第二天,甚至第N天后,你又把它切换到前台,当它显示PayloadView列表界面时,会发生神马?
那个today已不是今天了!!!
Why!?因为你把它放到闭包外面去了!
闭包会引用并保持一切外部它能看得到的值,然后一直保存着,直到再次使用它。
So,当闭包引用today的时候它还是今天,但是到了第二天后,today的值却变成了昨天了啊!
所以你的payload.wasCompletedAt(day: today).count,取得的就是昨天的负载数量咯.
你发现这个Bug了吗? ?
陷阱二: 1秒之前是这样,之后还是这样吗?第二个陷阱比第一个更简单,看你能不能一眼把它揪出来,直接上代码:
if self.isRunning{ // 若计时器处在运行状态则启动计时跟踪 watchTimerCount() // 略微延时以便完成lmtLbl大小的设置! DispatchQueue.main.asyncAfter(deadline: .now()+1.0){[unowned self] in // 计时器正在运行,需要播放运行动画 self.playFlowAnim() } }else{ // 略微延时以求更好的用户体验 DispatchQueue.main.asyncAfter(deadline: .now()+0.01){ // 计时器处在暂停状态,需要删除运行动画 self.removeFlowAnim() } }
上面代码在用户启动和暂停计时器时完成一些操作,做了大量简化。
So,上面代码有问题吗?
答案是肯定的,没有我说毛线呢???!!!
那么哪里有问题呢?问题就在那个延时!!!
你是在延时前判断的计时器状态,可是你能保证在这期间用户不会改变状态吗???
并不能!!!
你揪出它来了吗? ?
解决很简单,你在延时后再判断一次就行了。
So easy!
总结馅饼不常有,陷阱处处在!
小伙伴们需要擦亮眼睛,将Bug消灭进行到底!
正确找到以上2处Bug的小伙伴可以来领取超级豪华Bug大礼包 ?
就怕你们不敢要哦 ?