Optimal data store memory usage? - objective-c

I'm in the process of building a data store for keeping track of all the remote images being stored in my app. I've decided to use a singleton that will keep track of all the images being referenced.
As I remember, iOS automatically begins purging objects from memory based on recency of usage, whether or not it's being referenced by the current view controller, etc. However, if I store these images in a data store, those objects are always being referenced by the store itself. My solution for memory management was to keep track of when images were last called and keep some form of limit on the # and size of images being stored in the data store and purge the oldest based on age.
Is this solution a good one? Why or why not? Should I be depending on Apple's automatic memory management, or is having my own manager fine?
Further explanation:
Here's how requesting an image from one of my view controllers will end up looking with my solution:
[[HollerImages store]getImageWithUrl:#"https://www.google.com/logos/classicplus.png"
completionBlock:^(BOOL succeeded, UIImage *image){
if( succeeded ){
//Update the UIImageView with the returned image
}
}];
The store will then manage how many images are currently being referenced in the app and automatically de-reference old images as we hit some pre-defined limit. Thoughts?

Renaud Boisjoly (#rboisjoly) just sent me a link to this library which appears to provide the solution I was describing: https://github.com/rs/SDWebImage/

The easiest way to handle memory concerns is to just implement the -(void)didReceiveMemoryWarning function and clear out all your cached data there.
What you're talking about is implementing an expiring cache. You could just count the elements in your data structure at each insertion and remove elements from the head when you've hit the limit (provided it is an ordered data structure). The former solution is easier and works in most cases.

Related

Vuex store data always reside in memory?

First of all, I would appreciate your understanding of my poor English.
I wonder if Vuex's store data always resides in memory.
Let me explain with an example.
When entering page A, we received a list from the server and implemented it to be stored on the store.
Does this mean that when I enter page A and move to page B, the list of A will remain in memory even though it is not used?
Doesn't this cause memory overflow in very large applications?
The entire page state (including the DOM and Javascript/Vuex data) will remain in memory provided that a full page reload did not occur (which would be the case if you're using vue-router). This is called a Single Page Application (SPA).
In a SPA, you need to ensure that you drop any references (e.g. set to null) to large objects and arrays when they are no longer needed so that the memory can be freed by the garbage collector.

WinRT Storing Session State Between Page Navigation

I am new to WinRT and was playing around with session state. I am navigating to a page to collect data and then want to return to the main page. Just before navigation I am using:
SuspensionManager.SessionState["CurrentState"] = someObject;
The object contains lists of other mildly complex objects, etc... All seems to be working but is this the correct way to use the Suspension Manager?
I have looked at other posts on the topic and some people report that it is necessary to use [DataContract] and [DataMember] attributes to all the classes that are serialized. I omitted them and it still works, (getting the data across pages). So what is the recommended approach?
I may be reading too much into one aspect your question, but the role of SuspensionManager and SessionState is to store just enough information to bring your application back to the place the user left it if the application is actually terminated while it's suspended.
In the Windows 8 application lifecycle, your app gets 'suspended' if another app comes to the foreground. While your app is suspended all of its state is retained in memory, and if reactivated (you flip back to it) everything* is restored "for free".
A suspended app could, however, also be terminated by the OS (b/c of memory pressure, for instance) and there is no opportunity to react to that scenario in your app, so what you are really doing with SessionState is storing what's necessary to 'recreate' the last place the user was at IF the application had actually terminated. It's essentially an insurance policy: if the application is merely suspended, SessionState isn't really needed.
The 'what's necessary' is the grey area, I could store all of the information about say a user profile that was in progress OR I could save just the userid that indexes into my persistent storage of all the user profile data. I generally have more of a minimalist view and will retain as little as possible in SessionState - I make the analogy that I don't need to remember everything, I only need to remember how/where to get/find everything.
There's an implication as well in your question that you're using SessionState to pass information between pages in your app, and that's not really the intent. Each page of your app is typically connected with a view model, and when you interact with a page of that app, you'd update the view model and drive additional screens and experiences from the changes already in the view model. Leaving one screen of your app and returning the main one would also imply to me that you've persisted what ever information you collected - certainly to the view model, but also to something persistent like a data base or local storage. When you revisit that page, you'd then pull the data back out of your view model (or that persistent storage); the main page doesn't need that information so why hold on to it?
Lastly, since you mentioned being new to WinRT, you may want to check out App Builder, which pulls together a number of resources in consumable chunks to lead you through building an app over a period of 30-days (though all material is available, so you can consume at any pace you want :)) The discussion of lifecycle management that's germane to your question comes in on Day 17 of that sequence.
*"everything is restored for free" doesn't necessarily mean you don't have any work to do when an app comes out of the suspended state. There may be stale data that requires refreshing, and connections or other transient or short-lived entities may need to be refreshed/recreated.

managed object context take too long to load

I'm testing performance in my application, to see how it behaves with
a big load of data inside of it. My application is core data based and
uses array controllers in entity mode to fetch data.
What I discovered is that my app fetched all the managed objects
present in core data, so I set the fetch predicate of array
controllers at startup. This reduced dramatically the number of
objects fetched. The problem though is that my app still takes a lot
of time to start when is full of data.
I ran the app within instruments, and the core data fetches instrument
confirms that this is not the problem (my app fetches only 20-30
objects when starts). But running it under Shark I can see that for
4-5 seconds after startup the only call on the stack is to the app
managed object context. So I think it has something to do with
interaction between managed object context and data stored, even if I
don't fetch all the data. If I empty the app or leave little data
inside of it, it starts very quickly.
Does somebody know why this happens? Am I missing something obvious?
Why does it take so much to the managed object context to load if I
only fetch few objects? I always read that core data scales well and
the programming guide states that 10.000 objects are not much for core
data, but in my app it makes a big difference, so I'm wondering where
I am wrong.
amazing!
Just seconds after asking this questionI find the problem root and solve it !
Just for peoples who may face this problem :
you need to enable Use Lazy Fetching at the Object Controller for each NSArray Controller that you used in your application to solve the performance problem using core data managed object context
and here you go !
application starts as fast as you click on it !

Core Data over using?

I have an app that tracks a users driving trips (Paths). I save all the information using Core Data.
The db structure:
Path ->> Point
Point contains lat and long values.
What I do is, each time CLLocationManager is updated I add that point to an array. Once the user has reached the end of the path, I loop through and add all those locations to the db.
My question is...is this the best way to go about this? My two options are:
Add all locations to array, then add all locations to core data.
Each time CLLocationManager is updated, add that directly to core data.
I'm not sure if there is some best practice to accessing/altering core data. Should I do it in bulk (for loop), so that I can call
if ([managedObjectContext save:&error]) {
// handle save error
}
at the end of the for loop and keep it all condensed.
Or should I simply add a new Point each time CLLocationManager updates calling [managedObjectContext save:&error] after each update.
The only concern I have with Option1 is that if the app crashes while recording a path, none of the information will be saved.
So a benefit of using Option2 is that the data will be saved after each update but I'm not sure if accessing core data this frequent is bad practice.
Thank you very much for taking the time to help.
With the assumed frequency of NSLocationManager updates (max every few seconds) it is absolutely fine to save frequently. Also, your array will eat up more and more memory which is not really necessary.
You could still do it in discreet quantities, say, one save every 10 points.
Also you should perhaps save in applicationWillResignActive in case the app is interrupted.

Is it good practice to work directly with core data whenever I need to manipulate my business objects?

For example. if I have a chat app that uses objects like: ChatRoom and ChatMessage. (both subclasses of NSManagedObject)
And throughout the app I need to: search chat rooms / add massages / create chat rooms and messages / and any other manipulate.
Is it ok if I do everything directly with core data? I mean every time I need to search a chat room or something like that, to do it with NSFetchRequest or NSFetchedResultsController.
You can access the data whenever you need, of course. On the other hand you should try to use caching mechanism as much as possible.
For example, if you are using your data in UITableView you should defintely go with NSFetchedResultsController as it was created explicitly for UITableViews. From the apple docs on NSFetchedResultsController:
It optionally monitors changes to objects in its associated managed object context, and reports changes in the results set to its delegate (see “The Controller’s Delegate”).
It optionally caches the results of its computation so that if the same data is subsequently re-displayed, the work does not have to be repeated (see “The Cache”).
Otherwise, if you need the data just temporarily, you can access them of course using NSFetchRequest each time they are needed or cache them in your business objects if they don't change or you know their lifetime otherwise.