I've got an app which stores images taken by the camera in a table view. I have a problem where the images (using apple's queuing system for memory management) are not able to load as fast as the user can scroll (it stops then jumps when the image loads) and sometimes the app crashes. This is on an iPod 5. I understand that this is because of the fact it cannot load the images quickly enough. Does anybody have any suggestions for how to do this? I know it can be done because of the existence of the music app and such.
Thanks.
Check out this great tutorial.
http://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift
It uses NSOperation to achieve your goal.
Load images in background thread. You can use Dispatch_async or NSOperationQueue to get images in background. Your main thread will continue executing UI events.
Related
My iOS app launch screen takes about 3 - 5 seconds. I have a map that will load after the launch screen. My users have to wait for the launch screen to load and then wait another 3 seconds for the map to load.
Is there a way to minimize launch screen time?
Basically this delay means that you are doing something very wrong during launch. Your job is to launch immediately. Indeed, the WatchDog app will kill you dead if you don't.
There are excellent WWDC videos on this topic, and you should watch them. But in general there are two ways to go wrong:
You must do nothing time-consuming on the main thread. If you have a time-consuming thing to do, like loading your map or networking, you must do that on a background thread. You need to get out of the way so that the runtime can launch your app now.
Just the other way around, you must not touch the interface on any other thread but the main thread. Doing this wrong causes just the kind of delay you are reporting. Do your work on a background thread, but then get back on the main thread to talk to your views, view controllers, etc.
Finally, I should point out that you might be able to get some idea what you're doing wrong by using Instruments. Unfortunately it works rather badly against app launch, but it can be worth a try. Above all, watch those videos!
It seems that the api replaceCurrentItemWithPlayerItem: will stuck the main thread for some seconds, I understand that replacing the item need the information of the new item which might take some time to preload. But questions come up that why replaceCurrentItemWithPlayerItem: with a nil item object would also stuck the main thread?? It happens to me that sometimes it take more than 5 seconds to replace a nil playerItem.
I wonder what can I do to avoid the issue. Thanks for any advices!
I came across a similar blocking UI thread issue when I used UICollectionView to display and preview video in local photo library via ALAssetLibrary.
The scroll on switching videos is not smoothly,so I guess some method block UI thread.Then I use Core Animation of Instruments to analyze what exactly occupy the UI thread.In Time Profiler I found out that replaceCurrentItemWithPlayerItem need about 30ms to execute in main thread,which is more than 16ms (1000/60(fps)) result in choppy scrolling.
To solve the problem,first I tried that put replaceCurrentItemWithPlayerItem in to background thread using GCD,but It not work.I'm not sure if it is because the Cocoa itself need update UI when call replaceCurrentItemWithPlayerItem,which means the UI thread is still block.Finally I made it work by putting replaceCurrentItemWithPlayerItem at the scrolling end (the delegate func scrollViewDidEndDecelerating(scrollView: UIScrollView)).Now the scrolling is smoothly,yep!
Therefore,my advice is obvious : Using Instruments to analyse what exactly occupy the UI thread
I'm not sure how to efficiently capture the screen on a pixel-dense iOS device such as the iPad 3 (2048x1536). I've seen some examples such as this & this:
However, these solutions are too slow. I would like the view to be periodically captured maybe a few times a second, but the capturing mechanism is slow enough that if I executed this in the main thread, the UI would lock up. I was wondering whether it's possible to somehow delegate this to a background thread? Or perhaps there's a more efficient view capturing function? Thanks in advance.
I have an app that generates a PDF and displays it at the same time. As expected, there is about a 2-second delay between pressing the "Generate PDF" button and the QLPreviewController presenting the document. Not only that, it appears as though the document fades in momentarily, freezes, and then completes the fade-in.
I understand that the reason for the delay is because it is generating the PDF first, but the design of the application doesn't allow for any other mechanism. I was hoping to put a brief "LOADING..." animation before the QLPreviewController view appears, but everything I've tried so far still presents a 2-second delay.
Can anyone provide guidance on what I might be able to do here?
There are lots of options. I'd suggest that whatever you do, it be asynchronous. This will allow for the UI to not 'freeze' and you can put a loading screen up even if it is for 2 seconds.
There are many ways to implement this. Some involve actual background threads and others don't.
You can use, delegates, NSNotifications, blocks, NSOperations, and/or Grand Central Dispatch.
Here's a tutorial on how to use Grand Central Dispatch
Here's a tutorial on blocks
For better performance on scrolling the UItableView. I was adviced to draw the cells in a background thread.
But some one said that, update UI in background thread is not recommended, this can crash the app.
Is it possible to draw cells in background thread?
You very well can draw on a background thread - and then capture that drawing as an image and send that back to the main thread; there an image view displays the image you draw in the background.
If you have access to the Apple developer site, watch the WWDC 2012 Video "Building Concurrent User Interfaces on iOS". You don't want to actually lay out UIView instances and so forth but just use the various Core Graphics drawing functions.
You can not do that , every view would draw itself at the time when it comes to foreground, it would do nothing in background.
Drawing UI in background not only can crash but in most cases will crash the app.
Make sure you're using dequeueReusableCellWithIdentifier: message for getting cells.
Revise your tableView:cellForRowAtIndexPath: delegate to find what consumes most resources. It could be, e.q. hard UIImage processing or something similar. You should consider move all the processing, generating data and such things out of your cell creating. Only set appropriate data in cell and return it. I'm pretty sure it'll reduce your performance issues greatly.