Sending two separate asynchronous threads in Swift

I am trying to load a set of buttons that will move one after the other when loading a menu. So I did this:

    buttonTimer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(MainMenu.enterButtons), userInfo: nil, repeats: true)
    buttonTimer.fire()

      

This will trigger the enterButtons () method, which will trigger the move action for the buttons. This timer is created during the initializer of this menu, because I want the buttons to be loaded in init. However, during my initializer, I also initialize the class, which has high performance, since it contains 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 it in async because if I didn't, it would run all other initializer functions. However, I think these two streams are actually one. Order of asynchronous tasks:

  • Initialize the level holder
  • Download buttons

I was hoping these two tasks would run at the same time. However, it seems that instead of the three threads I was hoping for (the main thread, the one for the level holder and the download button), I believe there are only two: the main thread and one for the two async tasks that I created. During the debugging session, I noticed that the Load Buttons task is waiting for the level holder to initialize . However, I want to create three separate asynchronous threads. How can i do this?

Edit

I am trying to achieve concurrency for the level holder I tried, 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 am getting the error:

LevelHolder does not convert 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 to do 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 to warn I

cannot force expand the custom type "LevelHolder"

initialLevel is initialized inside the method that initializes the 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))
    }
}

      

This is an instance variable of this menu, defined as

var initialLevel : InitialLevel!

      

+3


source to share


1 answer


You immediately return your Holder level code to the main thread and set the time of the button to start after 0.1 seconds and then manually start it, which happens after the method completes. So everything happens in the main thread, and the levelHolder processing causes the buttons to be processed.

You can put levelHolder handling on a background thread like this:

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))
}

      



However, don't forget that updates to the UI should still go back to the main thread, like this:

DispatchQueue.main.async {
    // Update the UI
}

      

Unfortunately, nothing can be done about this, as all UI updates have to happen on the main thread, so they will block each other to some extent.

0


source







All Articles