I have an iOS app with some performance issues. In particular, when the user selects an item in a particular Core Data-backed UITableView there's a delay before the UI updates. Since there's very little multithreading in the app at the moment, I'm guessing I'm making a method call somewhere that's taking too long and blocking the UI thread.
Stepping through the code isn't revealing anything to me. (Perhaps because the problem is on another trip through the run loop? Not sure...I'm a solid iOS developer but a novice when it comes to the debugging and profiling tools.)
What's the best way to tackle a problem like this? Some way to step through or trace what the thread is doing in order and how long each call is taking, or something?
Thanks.
Check out the Time Profiler in Instruments. See WWDC 2012 - Building Concurrent User Interfaces on iOS for a practical demonstration of how you can use profiler to identify candidate methods that you might want to put in a background queue to avoid blocking the main queue.
See the Instruments User Guide for a basic description of the Instruments tool, but I think that WWDC video is a more effective way to gain familiarity with this particular instrument, the Time Profiler. Also, if you've never done concurrent Core Data, you might also want to see the Concurrency with Core Data section of the Core Data Programming Guide.
I will second what's Rob said: you will find more easily what's the bottleneck of your app using Time Profiler in Instruments. All references from Rob are good specially the one from WWDC. I also run into this tut in mobile tuts which covers the basics.
Related
I have sometimes app freezing I do not know what is the source of problem.
It happens rarely but happens. I consider how to track such issue
I have crashlytics from firebase but there is no errors as freezing is I suppose something with threads maybe some deadlocks or infinite loops.
Is there way to track such things?
What maybe reasons of app freezing and being inactive (it is SwiftUI app) ?
Are there possibilities to track/profile apps installed on devices (not connected via Xcode) and send informations such that are available in Instrument to something like firebase console or other 3rd party tools.
Update
I think I do not indicated important fact.
It freezes UI definitely not for a few seconds but app need do be killed and restarted again.
There might be some heavy process that locks your main thread, so it freezes your UI.
You track the problems, performance, leaks and more using Instruments.
There are sample topics:
Instruments Tutorial with Swift: Getting Started
How to find and fix slow code using Instruments
And WWDC videos like
Using Time Profiler in Instruments
Creating Custom Instruments
I have experienced some of these weird behaviours before. And mostly the reason behind it was a task that is blocking the main thread making it unresponsive. Pause the app and check the stack trace. Also make sure all your UI operations are done on the main thread. Hope this helps!
I have an application that can run for quite a long time scanning a database.
During this process I keep my program responsive by using processmessage.
This processmessage is triggered when my progress bar is updated and inc'ed.
This works fine is most cases, but when the databases get larger it takes longer for the progress bar to jump up 1%, the program becomes unresponsive until that time.
Is there another way to keep my program alive besides processmessages?
Multi threading is the answer. A standard Delphi application is basically a single threaded application that can do one thing at a time. Hence the gui lockup, it can't remain responsive if it's doing something else.
If you want to have a responsive gui and do heavy lifting at the same time, you need to have the heavy lifting in a separate thread or threads. This way your main thread can make sure you have a responsive program and the worker threads do the heavy lifting.
This works nice for heavy database work but also for for instance the downloading of files or situations where an answer of for instance a remote server can take a long time.
But this answer will probably give you more questions then answers because to explain HOW to use multi threading would be too big of an explanation for this question.
One other thing though: have a long and hard look at your database code. How are you retrieving records from the database, are there good indexes on the database etc. etc. etc. You can get insane speed improvements by optimizing this code before you have to start thinking about multi threading.
I've found the following resource: http://thaddy.co.uk/threads/ which you can download with pictures at: http://cc.embarcadero.com/item/14809 to be very usefull threading tutorial.
If you want to make your GUI program appear responsive, you must service the message queue in a timely fashion. There is no alternative.
When it comes to running database queries, the way to do that without freezing your UI, is to move the query to a different thread.
I have a game that I'm getting ready to submit. I've tested it a lot and it seems to be solid -- no crashes and no unexpected behavior. I am not forcing anything to run on the main thread (except for one place where I followed a sample in a book) and now I'm concerned that under some circumstance, on somebody else's device, the game will not work right or crash because I'm not doing something on the main thread that should be on the main thread. But I don't understand what needs to be run on the main thread. I googled for a checklist or summary of what methods need run on the main thread and didn't find anything useful. Is this something I need to worry about? The app is for iOS 5.1 and up and it uses in-app purchases and Game Center. I use the cocos2d framework and also a lot of UIKit stuff.
most methods running on the main thread are fine,
especially the UI,
you want to use the back thread for processes that can take long, like http requests, database or data sorting, or any other process that can pause the user experience while is processing.
if you load lots of objects you can produce a memory warning that can result in a crash,
so you can release non needed objects when you get a memory release.
good luck
I have an iPhone app which pretty much is a mobile app for a website. Pretty much everything it does is call API methods from our server. The app retrieves the user's information, and keeps updating the server using the API.
My colleague and I had a discussion whether to introduce GCD to the downloading aspect on the app. My colleague argues that since the UI needs to wait for the download to complete before it can display the pictures, text or whatever, there is absolutely no need for GCD. My argument is that we should keep the main thread busy with UI rendering (even if there is no data), and introduce GCD to the app to create other threads for download.
Which argument is right here? In my case, if the UI renders with no data, will there be some sort of lag? Which will yield a cleaner, sleeker and faster app?
One argument would be : what will happen when the download fails and times out because there is a problem at the server end ?
Without GCD the app will remain blocked and will crash after a time
out since the UI can not be blocked for longer than 20 seconds.
With GCD the application remains functional but there will be no data
being downloaded and the application will not crash.
Other aspects to take into account are :
the thread safety of the objects that you are using
how you handle downloads that are no longer necessary because the user navigates away from the page
I don't think doing time consuming operations in the main thread is a good idea.
Even if user have to wait for the data te be downloaded before he can do anything meaningful, still he will not hope UI is blocked.
Let's assume you have a navigator view, and after user tap some button, you push a new view to it and start download something. If user suddenly decides he don't want to wait anymore, he tap the "back" button. If your downloading operation blocks UI, user will have to wait it to end, it's really bad.
A more appropriate question would perhaps be if you should download asynchronously or on the main thread for your app, since there are several different methods to download asynchronously on iOS (e.g. using NSThread, NSOperation or indeed GCD). An easy approach to achieve your goals could be to use the AFNetworking library. It makes multithreaded networking / internet code very easy to implement and understand.
Personally I'm very fond of GCD and recommend you learn it someday soon, though in itself it is not as suitable for asynchronous downloading compared to a library like AFNetworking (that uses GCD under the hood, I believe).
Here is a good read on using NSOperationQueues (that uses GCD behind the scenes) to download images. There is also some Github code you can check out. They have an elegant solution to pause downloads and enqueue new downloads when the user moves to different parts of your app.
http://eng.alphonsolabs.com/concurrent-downloads-using-nsoperationqueues/?utm_medium=referral&utm_source=pulsenews
Use GCD / NSOperationQueues as opposed to using NSThreads. You will have a good learning on core fundamentals and at the same time create a well architectured app. :)
We are developing an IPad application with synchronization support, this synchronization logic is launched at the startup of the application to check if there are any updates by invoking a WCF service.
As the synchronization process takes time, we would like to put it on a background worker to not block the user interface, so my question is:
is it possible to develop a background worker that synchronize the sqlite database on background and on the same time the user interface is using this database? If it's possible can you please provide code or links to help me implement this?
Thank's in advance
This is definitely possible. What you are referring to is Threading where a process is done in the Background. Read up on Apple's Thread Programming Guide and Concurrency Programming Guide to get a better idea on how exactly it's implemented in iOS