becomeFirstResponder Memory Problems - ios

I have a hidden UITextField that when a the user is required to enter a character from the keyboard is sent:
[txtField becomeFirstResponder]
This text field has an event on editing changed that then calls a function to handle what was entered how I need it.
The user then selects an okay button that calls the following:
txtBox.text = #"";
[txtBox resignFirstResponder ];
I have tracked some memory problems all the way through to the line [txtField becomeFirstResponder]. When this is called, my Apps memory usage doubles on the spot and I receive a memory warning (even though code run). If I remove it (I have no keyboard of course!) but the memory issue goes away. I have read and tried a few approaches like removing the keyboard at Delegate level but without success. I am almost at the point of creating my own Keyboard.
Even though it is a lot I could probably work with this increase providing it would get properly released once I dismiss the keyboard - but it doesn't. The footprint of the App just gets heavier and heavier and for the life of me I cannot work out why.
First question is, is it possible that above is causing me the problem? I presume it is unlikely.
If not, any suggestions where to look / why I would receive such a rapid increase?
Heres a screenshot of Instruments - red line indicates where I call becomeFirstResponder:
http://i.stack.imgur.com/E7PaU.png
(they wont let me upload it - sorry!)

That isn't a good way to track memory leaks/problems. If there is a memory leak, instruments will show a leak, and that you can fix. You shouldn't assume the OS will free up memory just because you closed the keyboard (if anything, it probably is lazy loaded and cached).
Though I never had a problem with that, It is possible that your memory footprint increases when you show the keyboard. You didn't say how much memory is actually being used, so I will assume it is a small app and doubling that when opening a keyboard should be fine.
The OS caches all frozen open apps so memory is always tight. When receiving memory warnings clear what you can and let the OS handle the rest. If needed it will kill background apps. It doesn't mean that something is wrong with your app.

Related

How to save memory used in subviews as my iOS app enters the background after the App snapshot has been taken

I see a lot of posts about people trying to obscure sensitive information from their app snapshot so that its not readable in the multitasking app selector. But I have a different problem.
I'm trying to save as much memory in my app as possible when it enters the background, and one of my app's views has a lot of subviews that is the largest memory usage of my entire app. I've written code to remove and delete these subviews, which i then recreate when the app returns to the foreground (I've actually called these methods in the resign active and did become active methods). Everything is working fine but when I delete these subviews, the view correctly appears rather empty, just in time for the system app snapshot to be taken. So as the app is restored this empty view is displayed for a short time before the app renders properly.
I'd like to be able to manage these views but I guess it needs to happen AFTER the app snapshot has taken place.
Actually profiling the app's memory usage I've noticed that the large (70meg) memory usage that's present whilst the app is in the foreground drawing these views drops right down when the app is backgrounded even if i don't manually delete the views myself. The documentation is clear that the actual backing CA layers etc are all handled by the system so thankfully the majority of memory savings are already being made by the system itself. But still there's another 5-10meg that I can save by doing what I've described here so it feels like a good idea. Is it possible though?
I wonder if I should request to be left running a little longer which I think i saw was possible may be the solution? Especially if the app snapshot is taken before this extra time is given to the app.. This would mean the screenshot is correct and the memory is saved a split second later.
Thanks for your time, Cheers!
I'm not sure why you're worried about 5-10 megs of RAM. The system will reclaim lots of memory by blowing away the backing layers, as you said, and recreating them when the app is foregrounded again. But what, exactly, do you hope to accomplish by reclaiming more memory yourself?
Unfortunately you can't control when the snapshot is taken. You could, I suppose, do a dispatch_after to have your view destruction code happen after a delay, but this wouldn't be deterministic since you don't know when the snapshot will be taken. And it's also possible that the code won't be run at all if your app is asleep when the dispatch timer goes.
I think you may be optimizing prematurely.
Add a snapshot view on top of your view hierarchy before removing the subviews.
UIView *snapshotView = [view snapshotViewAfterScreenUpdates:NO];
Not exactly sure that will help save much of those few MBs you worry about, but that's the common way of doing something like this.

iOS custom keyboard extension - Memory Limit

I am developing a custom keyboard in which I'm ridiculously facing the memory issue. I did all kind of instrumental observation and came to the conclusion that iOS is preserving the memory every time keyboard is appearing and invalidating. I'm very much frustrated of this behaviour because as in dealloc I'm already releasing all of my DMA though my project is in ARC.
Scenario is something like this:
When I starts my keyboard for the first time it consumes approximately and after some operation it use to increase upto 30 MB and then I invalidate the keyboard. Again when I'm reloading it at that moment it starts from 30 MB which is totally unexpected and due to which after some transitions there is memory pressure and extension gets crashed.
It will be very much helpful if anyone can suggest some idea to manage memory pressure.
Short answer here is that you have a memory leak.
If you are writing you extension in Swift, add a break point to the deinit method in view controller that inherits from UIInputViewController and see if it gets called.
If you are writing your app in Objective-C then you can do the same thing from the deconstructor.
I too struggled with this and from my experience, the only thing that will stick around after closing the keyboard is some Core Data stuff. Other then that, if all your objects are owned by the primary view controller (UIInputViewController) then they will go away if they are no longer referenced.
If you still see a large amount of memory being used after the deinit is called then you have a leak elsewhere. Watch out for retain-release cycles and be careful with closures in Swift. Those are usually the culprits when it comes to memory leaks.
Without seeing any of your code I can't really provide any more specific information here.
Good luck!

Is it possible to increase keyboard first launch performance in iOS

There is always a delay (2-3seconds) on the first time the keyboard got invoked in application. Is there a method or a trick to improve this experience? I tried to use NSTreading, but it crashes on error "only perform on Main Thread" if I use [textfield becomeFirstResponder]; Any ideas?
As a general rule, do not try to touch UI elements from a background thread unless the documentation specifically states that it is thread-safe.
In your case, attempting to preload the keyboard in the background will not work. Keep in mind that the keyboard isn't created just within your application — it's shared across the system. That means if the system decides it needs to clear up some memory it will most likely "uncache" the keyboard if it's not visible.
If this is occurring in the Simulator, that's most likely because you're quitting the Simulator after every test run. As a result, the keyboard has to be loaded each time you run a test. If this is happening on a device, however, then most likely your device is frequently running low on memory.
That being said, if the instant showing is incredibly important, you could always try to use the old trick of making an invisible UITextField first responder, then immediately resigning first responder in order to force the keyboard to load.
maybe try a different keyboard? or try going into setting and looking at the input options, and go to keyboard. most of the time its because the programming is lagging, or you have more programms running in the background

iOS crash - no leaks, NSZombie enabled and doesn't breaking on exceptions

I am writing an iPad app which uses an AVPlayer to display a video. There's buttons to jump to various parts of the video, and when the user rotates the device, I change the size of the view which holds the AVPlayer layer.
My problem is that after a certain amount of device orientation changes and jumps around the video, the app crashes.
I have NSZombie enabled - this doesn't break.
I have a breakpoint enabled in my code to catch exceptions - this doesn't break.
I have run instruments and the code isn't leaking.
Allocations simply shows the "Overall Bytes" growing and growing with every action until it hits 14 meg and the pad crashes.
I feel like I have no way of getting to the bottom of this. Am I missing some trick to solving this? Does AVPlayer need some special treatment when being released?
ANY HELP, MUCH APPRECIATED.
Use instruments to check your Allocations. I recently had a very similar problem where there were no memory leaks but my Overall Bytes kept growing every time I launched a particular ViewController (and it would eventually crash).
It turned out that the ViewController itself was a strong reference as a delegate to another class (oops) and each time I dismissed the ViewController that other class still had a reference to it. Therefore each time I launched and dismissed this ViewController I would create another instance of it that would never die (and never leak).
Your exact problem may be different but you should be able to see the reason for your Overall Bytes growing by checking out your Allocations.

iOS not always calling didReceiveMemoryWarning

I'm looking for help with a very specific memory-management issue where didReceiveMemoryWarning doesn't appear to be getting called in cases where it should be.
I have a straightforward app that's a story with pages. I have an outer view/controller that manages the page views/controller. Each page view has a picture on it of decent size (200-300k). It's large because it's a universal app, so they're all 1024x768, then get scaled down for the iPhone. I have implemented didReceiveMemoryWarning to release unused controllers (whatever's not showing at the time). The app works fine when didReceiveMemoryWarning gets called, but it does not always get called. On the iPod Touch 2G, if I'm going from page to page fast, it will often just kill the program without calling didReceiveMemoryWarning (I put a breakpoint there to see). On an iPhone 1G which has the same amount of RAM, didReceiveMemoryWarning gets called at reasonable times and I never run out of memory.
The log prints "Received memory warning level 1/2" as expected right before my code does get called, but I don't see it in the logs in the iPod Touch 2G when my app gets killed without a chance to free up memory.
I've used static analysis and the leaks tool and the memory profile looks good. I don't think leaks have anything to do with the problem. Rather, the problem is that my program doesn't get the opportunity to free up resources when memory is tight. I do want to keep unseen pages in memory when there's enough memory - it allows for quick paging and makes the pan gesture for changing pages work responsively.
Has anyone else seen this? If anyone has hints, I'd appreciate it. I'm also curious if anyone knows under what conditions didReceiveMemoryWarning should get called. Is it possible that my program is gobbling up so much memory so fast that iOS doesn't have an opportunity to free up memory?
Memory warnings appear to come too late when allocating a lot of memory "too" quickly, especially if the app doesn't spend enough idle time in the run loop between allocations.
Try preflighting (attempt to allocate and then release) memory, and return to the run loop, maybe a half second before you really need the memory.

Resources