我正在尝试加载一组按钮,这些按钮将在加载菜单时一个接一个地滑动。所以我这样做了:
buttonTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(MainMenu.enterButtons), userInfo: nil, repeats: true)
buttonTimer.fire()
这将运行enterButtons()方法,该方法将运行按钮的移动操作。此计时器是在此菜单的初始化程序期间创建的,因为我希望按钮在init上加载。但是,在我的初始化程序中,我还初始化了一个性能很重的类,因为它保存了我所有的级别:
DispatchQueue.main.asyncAfter(deadline: .now()) {
self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))
}
所以我在异步中做了这个,因为如果我不这样做,它会占用初始化程序的所有其他功能。但是,我认为这两个线程实际上只是一个。异步任务的顺序是:
我希望这两项任务同时进行。但是,似乎不是我希望的三个线程(主线程,级别持有者和加载按钮),我相信只有两个:主线程和一个我创建的两个异步任务。在我的调试会话期间,我注意到加载按钮任务等待初始化级别持有者。但是,我想创建三个独立的异步线程。我怎么能这样做?
修改
我尝试为我尝试过的关卡持有者实现并发,@ UpholderOfTruth建议:
DispatchQueue.global(qos: .background) {
self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))
}
但我收到的错误是:
LevelHolder无法转换为'LevelHolder!'
因为self.initialLevel.levelHolder属于LevelHolder类型!但我将它设置为LevelHolder。
如何避免此错误?我试过这样做:
self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))!
然后Xcode建议警告我
无法强制解包为非可选类型'LevelHolder'
initialLevel在初始化级别持有者的方法中初始化:
func initializeLevelHolder() {
initialLevel = InitialLevel()
initialLevel.size = self.size
DispatchQueue.main.asyncAfter(deadline: .now()) {
self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))
}
}
这是定义为
的此菜单的实例变量var initialLevel : InitialLevel!
答案 0 :(得分:0)
您正在将levelHolder代码立即推回主线程,并将按钮时间设置为0.1秒后触发,然后手动触发,这在方法完成后发生。所以一切都发生在主线程上,你的levelHolder处理会阻止按钮处理。
您可以将levelHolder处理放到这样的后台线程中:
DispatchQueue.global(qos: .background).async {
self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))
}
但是不要忘记对UI的任何更新仍然需要返回主线程,如下所示:
DispatchQueue.main.async {
// Update the UI
}
不幸的是,由于所有UI更新都必须在主线程上发生,所以无法做到这一点,因此会在某种程度上阻止彼此。