Swift:运行代码会阻止其他代码,直到完成

时间:2018-06-16 03:09:40

标签: swift animation loading background-thread

我在ViewDidAppear中调用动画,稍后在ViewDidAppear调用一个函数创建几个UIImage对象数组,需要4-5秒才能完成。

同时动画只有0.8秒长,并且有一个完成块:

UIView.animate(withDuration: 0.8, delay: 0.0, options: UIViewAnimationOptions(), animations: {
            self.myView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
        }, completion: { finished in
            self.nextTask()
        })

问题是完成块在0.8秒后没有运行 - 它在上一代码完成之后才会运行。

我能做什么除了DispatchQueue.global(qos: .background).async的后台线程中运行该代码?或者有没有办法提高后台主题的完成速度?

如果在后台线程中完成,我的动画不会中断,但在后台完成需要更长的时间 - 比如20-30秒而不是4-5秒。

感谢您在此分享的任何帮助!

1 个答案:

答案 0 :(得分:2)

  

我正在调用一个创建多个UIImage对象数组的函数,需要4-5秒才能完成

你绝对不能在主线程上运行它。现代设备上的刷新帧为1/120秒。您不能导致帧丢失。当发生这种情况时,您将阻止用户交互。屏幕将被冻结,Watchdog进程将当场杀死您的应用程序。 (不幸的是,模拟器没有向您显示,也没有在设备上运行Xcode;但是如果您在设备上运行应用程序,请将其停止,然后从设备运行 而不是从Xcode运行,你会明白我的意思。)

  

问题是完成块在0.8秒后没有运行 - 它在前一代码完成之后才会运行。

正如你所推测的那样,这里有一个重新入侵的问题。您需要离开主线程以允许完成块发生。我真的很惊讶动画甚至开始(是吗?)。当你仍然在主线程上运行代码时,什么都不会发生。

您可以短暂延迟调用import os global items import json def items_get(): items = { "weapon":{}, "armour":{}, "potion":{}, "misc":{} } # Do not use \ as path separators in Windows. Use \\ (\t, \n, \' have speacial meanings) file_dir = ( os.getcwd() + '\\Code\\items.txt' ) with open( file_dir, 'r') as file_in: lines = file_in.readlines(); # ['WEAPON 3 sword_of_eventual_obsolescence 6 10 2 0 10\n', 'WEAPON 4 dagger_of_bluntness 2 5 3 1 0\n', 'WEAPON 5 sword_of_extreme_flimsiness 3 8 3 7 0'] for each_line in lines: # Use strip() to remove any leading/trailing whitespaces (\n, \t, spaces etc.) line = each_line.strip().split(' '); if line[0] == "WEAPON": weapon_id = line[1] name = line[2] attack_min = line[3] attack_max = line[4] range = line[5] weight = line[6] value = line[7] weapon_data = { "name": name.replace('_', ' '), "atk_min": attack_min, "atk_max": attack_max, "rng": range, "wt": weight, "val": value, } items["weapon"][weapon_id] = {} items["weapon"][weapon_id].update(weapon_data) return items # Calling items_get() to get dictionary items = items_get(); # Pretty printing dictionary using json.dumps() print(json.dumps(items, indent=4)) 以暂时跳出主线程,然后重新输入它,足够长的时间让刷新帧发生,这样系统就可以完成一些工作了。但这只是一种让动画开始的方式。一旦你回到主线程,你就会再次阻止它。

至于速度:{ "weapon": { "3": { "name": "sword of eventual obsolescence", "atk_min": "6", "atk_max": "10", "rng": "2", "wt": "0", "val": "10" }, "4": { "name": "dagger of bluntness", "atk_min": "2", "atk_max": "5", "rng": "3", "wt": "1", "val": "0" }, "5": { "name": "sword of extreme flimsiness", "atk_min": "3", "atk_max": "8", "rng": "3", "wt": "7", "val": "0" } }, "armour": {}, "potion": {}, "misc": {} } 的QOS是最慢的选择,所以你得到了你所要求的。但是,一般情况下,不要使用全局队列;建立自己的队列。我无法想象你在做什么可能需要这么长时间,也许这就是你应该真正要问的问题,但你绝对不能在主线上做到。