mashers
mashers

Reputation: 1089

Update UI with progress during UI-intensive loop

I've got a long-running loop which involves a fair amount of UI functions. This loop therefore must be run on the main thread. However, I also want to display progress of this task, so this must also run on the main thread as displaying the current progress would involve updating the UI. I am really struggling to find a way of allowing the UI to update with current progress on the main thread when the main loop is also running on the main thread. What happens is that the UI is frozen during the loop and then updates to show that the process is finished when it's done.

This is not for a production app, it's for a personal project that will never be release. So it is of no concern that the UI is frozen from a UX perspective. If the solution involves putting the processing in the background then this refactoring is fine, but I'm not sure how to do it when a lot of the heavy lifting during this loop involves UI stuff too.

Upvotes: 1

Views: 143

Answers (1)

mashers
mashers

Reputation: 1089

Isn't it funny how you sometimes come up with a solution just after posting the question?! The key seemed to be rather than using a for loop for the processing, instead putting the processing function inside a separate method and repeatedly calling it, passing the array of objects to process to it. Doing this, you can call the function using [self performSelector:withObject:afterDelay:]. Even if you provide a value of zero for the delay, it causes the method to be called on the next run loop. This means you can update the UI, process the next item, and repeat this process until the array of items is empty. Here's my completed solution. If anybody knows a better way I'd still love to hear it, but for now this is at least working!

Edit - I packaged this solution up into a class of its own to make it easier to manage, and put it on my Github. Maybe it will help somebody else out :)

Edit 2 - made the processing class more flexible by making it run loops instead of iterating through arrays. You can of course use it to iterate through an array yourself, as per the example in the readme. But if you're not working with an array, you can just run the loop runCount times and do whatever you need to do in the processingBlock.

https://github.com/mashers/BackgroundLoopProcessor

Upvotes: 3

Related Questions