It's hard for me to tell what's going on there, but there should be far more memory available even on that generation of device. I'm pretty sure that device has 256MB of RAM and a single app should probably be able to get about 100MB of it (maybe more) over time.
Semi-related and awesome device support matrix for iOS: http://www.neglectedpotential.com/2012/11/ios-support-matrix-2-0-winter-edition/
Your screenshots don't really show a scale on the graphs, so it's next to impossible to really tell how much memory is being used on them. However this one:
..shows Live Bytes which is the real memory being used right that moment - and that's super low and totally fine. Concerning numbers there are how huge Overall Bytes and Transitory are. You've allocated and deallocated nearly 1GB so far with over 2 million separate allocations! How long was the app running at that point? I suppose it's possible that you're running into memory fragmentation issues - there's plenty of memory left, but nothing in big enough chunks for what your app needs? It seems as if your app is allocating and destroying zillions of objects and really churning through a huge amount of memory (although I can't say for certain - maybe your app had been running for 20 minutes at that point or something and that's not a problem). Maybe try using more object pooling or something like that?
When iOS gets low on memory it takes time (seconds) to tell all the other apps to purge themselves and, failing that, kill them off to free up more memory for the running app. iOS also sends low memory notifications a whole bunch of times. There's a variety of esoteric reasons for that, but if you're being too clever in your low memory code, you could accidentally be causing more problems than you're solving. (Example might be purging something and then another frame renders and all those purged caches reload. And then you get another low memory notification and you purge everything again. Repeat.)
One of the reasons some of the bigger games have loading screens is to combat this, to some extent (and for other normal reasons, of course). Rather than loading all the big resources in a single function or method somewhere, they spread the loading out over time. Load a big texture. Delay for a tenth of a second. Load another big texture. Delay, etc. This allows iOS to send those low memory notifications to your app (which, if you're loading and active, you might want to ignore, actually), as well as other backgrounded apps and system apps. It gives iOS time to get rid of them. If your app tried to allocate big texture after big texture without letting the runloop cycle a few times in between, iOS may eventually decide your app is being an inconsiderate hog and kill it unceremoniously. 🙂