IOS - Modal UIView is loosing delegate after memory warning - ios

I've almost finished my iPhone app and I'm making test using XCode 4 and IOS Simulator.
My App has a series of view opened modal:
View 1 --> modal --> View 2 --> modal --> View 3 --> modal --> View 4
View 2 is the delegate of View 3 and View 3 is delegate of View 4.
If View4 is visible and I try to "simulate Memory Warning" then I'm able to go back to View3, but View3 is not able to call its delegate ([self.delegate NotifySave:self]).
If I place a breakpoint before calling the delegate, I see "0x0" instead of "0xsomething".
Even if I "quit" the application with the "home" button, the problem (of course) is still there when I run the app again.
The questions are:
Did someone else experienced the same problem?
Can this problem exists only with the simulator? (I'm not able to reproduce the warning on real iPhone)
Did someone have any suggestions?
Can I prevent View2 from being released? (I think this is the cause of the problem)
Thank everybody for the help.

If you are storing the delegate via obj-c 2.0 property, try changing your model to rely on a retain instead of assign. This will ensure that the delegate is not released out from under you in these situations. If you go with this route, it is important to ensure that you do not have a "retain circle" where two objects retain each other and never get released.
#property (nonatomic, retain) id delegate;
For backgrounding, you should develop a system that stores the info you need to restore your application state, then clear all these items out of memory on quit (in - (void)applicationDidEnterBackground:(UIApplication *)application) and restore them on relaunch. This will prevent your application from being "purged" as often, increasing the likelihood that you'll be able to restore on relaunch (in - (void)applicationWillEnterForeground:(UIApplication *)application), rather than your app being relaunched from square 1 each time.

Related

Loading the last View Controller Active after app goes into background, swift

I have "Tinder" like swipping view that is located in a CardViewController. The card View Controller is accessed by moving through two other view controllers. i.e. Load App -> FirstViewController -> SecondViewController - > CardViewController.
When I am in the Card ViewController and I go into background mode, the app launches on the FirstViewController and on going to the cards, they are loaded from the first card in a stack of about 10?
Is there anyway to load the app from the last Card I had swipped and in the CardViewController without having to navigate from the FirstView Controller again?
I would really appreciate the help as it's horribly affecting some of my users.
An example of a Tinder like card view is shown!
The problem, from the sound of it, is not what happens when the app goes into the background — that would leave it in exactly the same state when it reactivates. The problem is what happens when the app goes into the background and quits. Your app is then relaunched from scratch, which is why you find yourself in the first view controller. What's upsetting you is the difference between the app's behavior in these two situations.
Apple provides a solution to this situation: UIViewController, along with the App Delegate, has methods permitting you to save and restore state. When the app goes into the background, the current configuration (what view controller's view is showing) is saved. That way, even when the app quits, when it relaunches it can get back to that configuration before it appears to the user. Thus, coming back from background-and-quit looks just like coming back from mere backgrounding.
For full details, see Apple's documentation. This is a good place to start:
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/PreservingandRestoringState.html

Strategy to launch a task - and avoid race conditions - from the App Delegate

I'm developing a small app on top of core data. At startup, I need to launch a maintenance task - fast but important -. To run this task, the app delegate must open a UIManagedDocument, and perform various checks on it. The app views must not start until the checks are completed. Because opening a UIMD is asynchronous, the app delegate isn't done when the first UIview tries to access the doc. The application then crashes due to a race condition because the app delegate and the view are trying to open the doc at the same time, while the doc state isn't yet finalised.
I'm using a storyboard, so segues are pretty much in control of the OS... Next time, I'll do it all manually..
What would be your recommendations ?
Note:
1)I can not perform the task when the app. goes into background state, because if it is brought back up again, avoiding inconsistent states between the underlying database and what's displayed in the view will be very tedious.
2)For the same reasons, performing the maintenance task during normal execution is not easily done.
3) All views access the UIMD via a singleton, according to the code proposed here
Setting a mutex lock in the UIView isn't my preferred route, because the screen remains black - no data -, while displaying the tab bars, until it is released by the app delegate.
Is there a way to have the app delegate wait for a signal before it hands the control over to the UIViews ? In this case, are there any gotchas ? I suspect this is probably not the recommended way to do, and iOS might kill the app if the delegate stays too long waiting for the maintenance task to complete. What would be "too long" in this case?
You could do it more elegant way. The first view the user will see must be some kind of SplashView - just an image with progress indicator. It should stay on top while your task is going on. It's not too important how you're showing this view. You can set it as the first in your storyboard or just create it manually in applicationDidFinishLaunching message.
Then in your task send a NSNotification when it's about to finish and in the observer in your AppDelegate just hide your SplashView and present your first view with valuable content.
You can even add some visual effects for transition between those views and your app will look really great! :)

iOS: Hiding sensitive information on the screen when app is backgrounded

When a foreground app gets backgrounded (e.g. Home button gets pressed), how can I change elements on the topmost view controller prior to when iOS takes a snapshot of it and starts the animation to show the next screen?
I ask because I'm writing an app requiring HIPAA compliance, and I am concerned that the snapshot that the OS takes in order to do this animation sometimes contains sensitive data which should not be visible even for a split second when the app gets foregrounded later.
I'm aware that view controllers have lifecycle methods such as viewWillDisappear which might be usable, but I have a lot of controllers and I'd rather just have something in my App Delegate to handle this (e.g. by adding an opaque full-screen UIImageView overlay) rather than having to write custom code for this in every last controller.
I tried putting overlay-generating code in applicationWillResignActive, and I've been digging with Apple's docs and Google, but it's not working. I suspect the screenshot gets taken before the app has a chance to update the screen.
Thanks!
Not sure about HIPAA's requirements about backgrounding and possibly leaving the user logged in for someone else to resume, but the safest sounds like it would be to add a key UIApplicationExitsOnSuspend with a boolean value of YES to info.plist.
That will prevent the app from backgrounding entirely, and restarts it (possibly triggering a login procedure) every time you go back to it.
Most (if not all) mobile banking applications I've tested do this for safety reasons.
I believe the answer is to not concern oneself with changing what's on the screen before the backgrounding animation begins, but to simply modify what's displayed on the screen once the app enters the background (i.e. inside of applicationDidEnterBackground: in your App Delegate.) This solved my problem.
My UIImageView overlay idea worked here, although I decided just to pop to the root view controller instead. Simpler that way. My root view doesn't have any sensitive info.
Here's what it looks like:
-(void)applicationDidEnterBackground:(UIApplication *)application {
UINavigationController *navigationController =
(UINavigationController *)self.window.rootViewController;
[navigationController popToRootViewControllerAnimated:NO];
...
}

iOS 5 View events order change

Has anyone noticed that the order in which view events are fired in iOS 5 has changed? Using a Tab Bar switching from one view to another, the order in iOS 4 was: "viewWillDisappear" and then "viewWillAppear". In iOS 5 they are switched. Is it possible to use iOS 5 but have the previous order of events?
This is true.
Seems that the tab's viewDidLoad now gets called BEFORE the app delegate's didFinishLaunchingWithOptions.
I had the app launch initialising something and the viewDidLoad customising it. IOS 5 messed it up until I made the app init routine leave things alone if they had been setup.
I am guessing that you need to be prepared for this and either make your code check in each place that nothing is being undone or corrupted by the other.

Memory issues in releasing a UIViewController with UITextField

I've some memory issues with a view controller that contains a text field.
Brief summary:
Clicking on a button my application modally presents a UIViewController (that I will call "VC1").
From VC1 the user can optionally open (using pushViewController) a UITableViewController ("VC2") and turn back.
From VC1 the user can optionally open (using pushViewController) a UIViewController ("VC3") and turn back.
Finally the user can dismiss VC1
VC2 and VC2 are referenced in VC1 as properties and they have to remain in memory. When the user dismisses VC1 then I release all.
VC3 contains a simple view with only one UITextField that becomeFirstResponder when viewWillAppear is invoked.
Issues:
When I open VC1 and then VC2, turn back and dismiss: it's all ok, the application returns to the same initial amount of "Live bytes" (that is 1,20MB). When I open VC1 and then VC3, bytes become 2MB. When I write something inside the text field allocations rise to 2,50MB
In this moment Instruments discovers a memory leak of 16byte with ProofReader as Responsible Library and PRRfInit as Responsible Caller
After turning back to VC1 and dismissing, the allocations remain to 2,50MB
Ordering by category in Instruments I checked that VC1, VC2 and VC3 have 0 live bytes, but the overall remains to 2,50MB
Is also involved the keyboard?
I'm assuming that you're testing on the device, not the simulator - the simulator produces incorrect results.
The total memory used by your app is fairly meaningless as a measure of memory leaks - the iPhone will try to cache as much data as it can while there is free memory - it will load libraries and leave them in memory in case you are going to use them again. It's only an issue when you start to run out and then it will sort it out for you.
And a 16byte leak from a library is fairly irrelevent (assuming it only happens once) - Apple's libraries end up leaking more than that in my experience.
There are many better ways to spend your time ;)
PS Is ProofReader a library you have included or one that's part of Apple's SDK?

Resources