I am trying to load a set of buttons that will slide in one after the other when the menu is loaded. So I did this:
buttonTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(MainMenu.enterButtons), userInfo: nil, repeats: true)
buttonTimer.fire()
That would run the enterButtons() method, which will run the move action for buttons. This timer is created during the initializer of this menu because I want the buttons to load in on init. However, during my initializer I also initialize a class which is performance heavy, since it holds all my levels:
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))
}
So I did this in async because if I did not it would hold up all the other functions of the initializer. However, I think those two threads are actually just one. The order of the async tasks are:
- Initialize level holder
- Load buttons
I was hoping that these two task would run simultaneously. However, it seems that instead of the three threads I was hoping for (the main thread, the one for the level holder, and the load buttons) I believe there is only two: the main thread and one for the two async tasks I created. During my debug session, I noticed that the load buttons task waits for the level holder to be initialized. However, I want to create three separate async threads. How can I do this?
Edit
I an attempt to achieve concurrency for the level holder I tried this, suggested by @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))
}
But I get an error that says:
LevelHolder is not convertible to 'LevelHolder!'
because self.initialLevel.levelHolder is of type LevelHolder! but I am setting it equal to LevelHolder.
How can I avoid this error? I tried doing this:
self.initialLevel.levelHolder = LevelHolder(screenWidth: Float(self.initialLevel.size.width), scene: self.initialLevel, screenSize: self.initialLevel.frame, initialLevel: (1,1))!
But then Xcode suggests warns I
cannot force unwrap to a non-optional type 'LevelHolder'
initialLevel is initialized within the method that initializes level holder:
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))
}
}
It is a instance variable of this menu defined as
var initialLevel : InitialLevel!
UIView.animate(withDuration:delay:options:animations:completion:)?LevelHolderstuff is happing on the main thread. There is no concurrency happening here so far, so no, this isn’t going to happen simultaneously. In terms of the desire to run stuff simultaneously, we’d have to see whatLevelHolderIs doing that is so resource intensive. Maybe there’s an opportunity to make some of that happen asynchronously. But simply dispatching something asynchronously to the main queue does not provide concurrency.