I am building application that uses tab bar.
I have say A & B tab.
When I click on tab A, then it takes time for loading data from server.
Similarly, when I click on tab B, it takes time loading.
If click on tab A and wait until it loads all data, and then move to tab B, it works fine.
If I click on tab A and move to tab B while A was still loading data from server, it crashes the app.
I tried to unload the view at view did unload method. But, it did not work.
Can anyone suggest me how to solve this problem?
in each view loaded by tab bar controller, I added self.view = nil; for each view will disappear method. This solved by problem. May be this will be helpful.
Without seeing your code, it's difficult to answer. There could be many possible causes. However, my first guess would be that you're dispatching your NSURLConnection completion handler to the main queue and trying to update the UI, which is no longer in sync.
In other words, you start on tab A and the download commences asynchronously. You then switch to tab B in your UI, starting the second download on another queue. Your tab A download completes, and the completion handler is then dispatched to the main queue. In that completion handler, you may have code to, for example, reload a UITableView on tab A. But since you are no longer on tab A, that view controller (and all of its associated views) do not currently exist in your program's life cycle. If you're not properly checking for nil responses, etc., this could create a crash.
Another less likely possibility is you are running out of memory. Easy to test for this: simply monitor the memory usage as you navigate through the app. Your app may crash if it doesn't properly respond to a memory warning. This would be possible if you were using an NSURLCache, perhaps, and committing too much memory to both download requests simultaneously.
Related
Basic question:
Is there a reliably way to trigger showing modal UIViewControllers at any point in the app's lifetime (including from different threads)?
My current approach is to call presentViewController on the showing ViewController (found through window.rootViewController + hierarchy traversing but that's unimportant). This generally works, but is sometimes ignored due to things like a navigation action/animation taking place.
E.g. a background thread signals for a popup to be shown, and presentViewController is called on a ViewController in the process of being dismissed.
I've tried a few work arounds such as repeating the signal if the ViewController isn't shown (which led to some instances of it being show multiple times), but it's ended up being a game of whackamole.
An ideal solution would also allow navigation to take place underneath the popup, but the primary issue right now is just reliability.
edit
To be clear, I’m a seasoned developer. The threading is being handled properly, the instance and type management is working. My problem is trying to manage all
the corner cases, not the basics of how to do it.
If you need mechanism for thread safe showing different VCs in multithread environment, you can make some object which is responsible for presenting/dismissing controllers. And make some queue on presenting/dismissing. So when your signal occurs, your operation on presenting will be next after dismissing current VC in queue
I am new in iOS and I have tab bar. I have 4 tabs like Facebook.
In my case all data should be updated from server anytime when user goes one of that screen.
One guy said calling viewDidLoad frequently can make memory leaks. Is that true?
So what's the best play here? Every time call viewDidLoad() and load data from server or there is another way to handle this not calling viewDidLoad() every time.
There is no pull to refresh in that screens
viewDidLoad() will only be called the first time the view controller is loaded. Using a tab bar controller will usually keep the view controllers in memory as the user switches tabs so if you want the loading to occur every time the user goes to a new screen, this is not the best place for it.
I would suggest using viewWillAppear or viewDidAppear. If you're updating data from the network, make sure to do the loading on a background thread to ensure the interface does not get blocked (regardless of which method you use).
Personally I would put network loading code inside viewDidAppear as to me it makes more sense to call the network after the view has finished appearing since it will presumably not finish immediately. This way it is also easier to present a UI element that shows data is loading to the user.
I have created a customise table cell in which i am downloading image in background thread in cell class and now suppose i moved to previous view controller. Would background thread still would execute and will crash the application. I could;t test this scenario as images loading fast and didn't get chance to move to previous view controller.
What would be the consequences?
Problems can certainly arise if you don't do this correctly. You probably won't get a crash, because the NSURLSession prevents that for you by retaining its delegate. But by the same token, the view controller you have left will leak; it won't go out of existence, and the downloads and other things will continue to happen.
If you are doing it correctly, all downloads should be cancelled by you when the view controller goes out of existence. If you don't need these downloads occupying bandwidth and CPU time, you have a duty to call invalidateAndCancel to make that happen. Note that you generally cannot do this in the view controller's deinit, exactly because of the retain cycle. But once you have done it, your view controller will be able to go out of existence in good order.
I am using uiwebview to show my web contents. Navigating to different url using RevealViewController. I am caching all the pages for the first time entry.
After visiting few pages when trying to goto rear view (reveal view controller menu screen), the app got stuck for some time on clicking of the menu button.
(Every time visiting and caching a page that will increase the memory size of the app)
If the presentation of the menu is slow, it is probably because you are doing some heavy processsing inside the initialiser of the menu or the viewDidLoad function, or the menu button pressed function.
My suggestion is to move any of that processing to the viewDidAppear method of your menu controller instead, so that the UI is not blocked by any processing you do. You could also use GCD to disaptch_async anything that is intensive.
If you give some code examples it will be easier to see exactly what the problem is, particularly the code that executes when the menu button is pressed.
How do I make a curled-up view update live as the user interacts with view being presented with presentModalViewController: under it?
The behaviour I want:
User taps a view settings button.
User taps controls in the view settings screen. Rather than dismissing view settings, the view automatically updates in the background.
User taps something to dismiss view settings.
Imagine if in Maps tapping Map, Satellite, Hybrid didn't uncurl automatically but just updated the display.
I'm able to get notification that something's changed from the settings controller back to the main view controller. The main view controller can update and signal that it should redraw parts of itself, but actually updating the screen is intermittent. It will work 5 times in a row, then not work a couple times, then work another 5 times in a row. Dismissing the modal view always catches up the view underneath, however, so I assume the rendered image of my view is sometimes being cached or not being redrawn despite my request. But I can't think of a way to verify this.
This happens on both the device and the simulator.
While there might be multiple root causes of this behavior, here's a common issue I've seen that causes 'delayed' or 'intermittent' updates to UIKit views.
If the statements that update your presenting view (or the presented view) are running in a dispatch queue other than the main queue, UIKit may produce inconsistent results and timing in the actual UI update. You can usually tell by putting a breakpoint on the statements that update the UI and examining the name of the 'queue' displayed in Xcode's left-side debugger view. It should be 'com.apple.main-thread'. If it's not, that could be your issue. This can happen in quite a few delegate methods such as the network APIs.
Try wrapping your UI updates in:
dispatch_async(dispatch_get_main_queue(), ^() { ... }); and see if that helps! You should only do this when needed and take care to use block-safe techniques as always.
I tested this in a brand new Universal app for iOS 7.0.3 using the iPad simulator with a view controller presented using the partial curl transition. I was able to replicate the original issue, including the intermittent update and the 'snap' update when dismissing the presented view by using a background queue in the code I provided above. Once I switched to the main queue, everything worked A-OK.
Let me know if this helps or if there was some other issue :)