iOS: best way to encode/decode memory intensive objects - objective-c

I'm fairly new to iOS programming and am struggling to decide on what is the best way to encode memory intensive objects using the NSCoding protocol.
I have a large number of Item objects. Each Item has numerous hi-res images associated with it. Additionally, each Item belongs to an ItemCategory, which may contain 100 Items.
As far as I can tell, I have a couple different encoding options:
Encode the entire ItemCategory object
Eliminate the ItemCategory class, create just an itemCategory property for each Item, and just encode the individual Item objects.
It seems to me that #1 would be wastefully expensive. In order to add a new Item to the ItemCategory, I'd have to decode the entire ItemCategory (which means decoding those hundreds of images tied to the Items it contains as well), add the Item, and then re-encode the whole thing (again, along with all those images).
But, #1 does seem to be the correct way to do it from a code-structure point of view. #2 forces me to come up with a less intuitive way for storing Items and associating them with their respective ItemCategories.
If I were to go with #1, is there a way to decode only certain parts of objects, so that I don't end up with all those images getting initialized when I don't actually need to display them? One thought that occurred to me is to not actually encode the Item's UIImages along with the Item itself, but rather just the image name. That way, the image would only get initialized when necessary, and could be released without releasing the entire Item if so desired. I suppose this is kind of a relational database type of approach.
I feel like there must be a standard way for handling a situation like this, no?
Or is my fear over memory consumption unfounded? Perhaps this could be seen as an example of "premature optimization", but the decision I make now will deeply affect the data structure of the application. Changing from option #1 to #2 down the road wouldnt be pretty :)

Perhaps you can use CoreData, and a persistentStore. CoreData makes it easy to manage relationships. You can create entities that have relationships that are managed by the system. So in your case, perhaps you can have an 3 entities: Category, Item, and Images, and a one to many relationship between Category and items, and a one to many relationship between Item and images, meaning that each category can have multiple items, and each item has multiple images, then when you need yo you can create new images and add them to a particular item, or search for all the images within an item.
I hope that this was clear, but CoreData is great for managing relationships and the data model is very easy to work with.

Related

NSManagedObject as store with continuous analysis of raw data

This is similar to a question I asked before, but now that I've come much further along I still have a question about "proper" subclassing of NSManagedObject as I was told last night that it's a "bad idea" to put lots of non-persisted properties and ivars inside one. Currently I have TONS of code inside my NSManagedObject, and Apple's docs don't really address the "rightness" of that. FYI: the code works, but I'm asking if there are pitfalls ahead, or if there are obvious improvements to doing it another way.
My "object" is a continuously growing array of incoming data, the properties/ivars that track the progress of the analysis of that data, and the processed data (output). All of this is stored in memory because it grows huge, very quickly, and would not be possible to re-generate/re-analyze continuously. The NSManagedObject properties that are actually persisted are just the raw data (regularly saved, as Core Data doesn't support NSMutableData), a few basic properties and 2 relationships to other NSManagedObjects (1 being a user, the other being a set of snapshots of the data). Only one object is being recorded to at any one time, although dozens can be opened for viewing (which may involve further processing at any time).
It's not possible to have the object that inserts the entity (data manager that manages Core Data) have all of the processing logic/variables inside it, as each object necessitates at least a handful of arrays/properties that are used as intermediaries and tracking values for the analysis. And I, personally, think that it sounds silly to create two objects for each object that is being used (the NSManagedObject that is the store, and another object that is the processing/temp store).
Basically, all of the examples I can find using NSManagedObjects have super simple objects that are things like coordinates, address book entries, pictures: stuff that is basically static. In that case I can see having all of the logic that creates/modifies them outside the object. However, my case is not that simple and I have yet to come up with an alternative that doesn't involve duplication.
Any suggestions would be appreciated.
You might use a 'wrapper', that is to say a class with a reference to one of your managed object instances, this wrapper would contain your algorithms and your non persisted algorithms.

Saving a list each time it changes

I'm writing an application where a user can add and remove objects from several lists. In order to save their lists even when the application crashes, I want to write them to the disk every time they change. My current plan is to create a class that observes the lists and thus is notified each time one changes, in order to archive them (the lists and all objects in them follow the NSCoding protocol).
It should be noted that I know in advance how many lists there will be, and that these lists are not expected to grow to more than 100 items in length (most will be 10-20).
Is this the best way to achieve what I want to achieve? Should this even be a problem I am worried about, or is it acceptable to only create mementos of these lists when the application exits? I was also considering subclassing NSMutableArray to make a class that saves itself whenever it changes, so that no one class must be aware of all lists that should be saved.
First, good instinct here to worry about the user's data. Yes, of course you should fix your crashes. But even so, you should be protective of the user's data first and foremost. Secondly you should be worried about the user's battery life. So you shouldn't hit their flash drive too often.
If the number of changes aren't large, then I'd recommend creating "list" objects that has-a NSMutableArray (rather than is-a NSMutableArray). You can just write yourself to disk anytime someone calls addItem: in order to always be in sync. If changes happen very quickly, it's pretty easy to build trampolines that will save "every second if there has been a change, but no more often than once a second." (If this is any problem, add a comment and I'll post some code or blog it; it's not difficult.)

How does one architect an entity in Core Data with a generic relationship?

Say you need to architect an app with an entity that can be associated with multiple other kinds of entities. For example, you have a Picture entity that can be associated with a Meal entity, a Person entity, a Boardroom entity, a Furniture entity, etc. I can think of a number of different ways to address this problem, but -- perhaps because I'm new to Core Data -- I'm not comfortable with any of them.
The most obvious approach that comes to mind is simply creating a relationship between Picture and each entity that supports associated pictures, but this seems sloppy since pictures will have multiple "null pointers."
Another possibility is creating a superentity -- Pictureable -- or something. Every entity that supports associated pictures would be a subentity of Pictureable, and Picture itself would have a one-to-one with Pictureable. I find this approach troubling because it can't be used more than once in the context of a project (since Core Data doesn't support multiple inheritance) AND the way Core Data seems to create one table for any given root entity -- assuming a SQLite backing -- has me afeard of grouping a whole bunch of disparate subentities under the umbrella of a common superentity (I realize that thinking along these lines may smack of premature optimization, so let me know if I'm being a ninny).
A third approach is to create a composite key for Picture that consists of a "type" and a "UID." Assuming every entity in my data model has a UID, I can use this key to derive an associated managed object from a Picture instance and vice versa. This approach worries me because it sounds like it might get slow when fetching en masse; it also doesn't feel native enough to me.
A fourth approach -- the one I'm leaning towards for the app I'm working on -- is creating subentities for both Picture and X (where X is either Meal, Person, Boardroom, etc.) and creating a one-to-one between both of those subentities. While this approach seems like the lesser of all evils, it still seems abstruse to my untrained eye, so I wonder if there's a better way.
Edit 1: In the last paragraph, I meant to say I'm leaning towards creating subentities just for Picture, not both Picture and X.
I think the best variations on this theme are (not necessarily in order):
Use separate entities for the pictures associated with Meal, Person, Boardroom, etc. Those entities might all have the same attributes, and they might in fact all be implemented using the same class. There's nothing wrong with that, and it makes it simple to have a bidirectional relationship between each kind of entity and the entity that stores its picture.
Make the picture an attribute of each of the entity types rather than a separate entity. This isn't a great plan with respect to efficiency if you're storing the actual picture data in the database, but it'd be fine if you store the image as a separate file and store the path to that file in an attribute. If the images or the number of records is small, it may not really be a problem even if you do store the image data in the database.
Use a single entity for all the pictures but omit the inverse relationship back to the associated entity. There's a helpful SO question that considers this, and the accepted answer links to the even more helpful Unidirectional Relationships section of the docs. This can be a nice solution to your problem if you don't need the picture->owner relationship, but you should understand the possible risk before you go down that road.
Give your picture entity separate relationships for each possible kind of owner, as you described in the first option you listed. If you'll need to be able to access all the pictures as a group and you need a relationship from the picture back to its owner, and if the number of possible owner entities is relatively small, this might be your best option even if it seems sloppy to have empty attributes.
As you noticed, when you use inheritance with your entities, all the sub-entities end up together in one big table. So, your fourth option (using sub-entities for each kind of picture) is similar under the hood to your first option.
Thinking more about this question, I'm inclined toward using entity inheritance to create subentities for the pictures associated with each type of owner entity. The Picture entity would store just the data that's associated with any picture. Each subentity, like MealPicture and PersonPicture, would add a relationship to it's own particular sort of owner. This way, you get bidirectional Meal<->MealPicture and Person<->PersonPicture relationships, and because each subentity inherits all the common Picture stuff you avoid the DRY violation that was bugging you. In short, you get most of the best parts of options 1 and 3 above. Under the hood, Core Data manages the pictures as in option 4 above, but in use each of the picture subentities only exposes a single relationship.
Just to expand a bit on Caleb's excellent summation...
I think it's important not to over emphasize the similarities between entities and classes. Both are abstractions that help define concrete objects but entities are very "lightweight" compared to classes. For one thing, entities don't have behaviors but just properties. For another, they exist purely to provide other concrete objects e.g. managed object context and persistent stores, a description of the data model so those concrete objects can piece everything together.
In fact, under the hood, there is no NSEntity class, there is only an NSEnitity***Description*** class. Entities are really just descriptions of how the objects in an object graph will fit together. As such, you really don't get all the overhead an inefficiency of multiplying classes when you multiply entities e.g. having a bunch of largely duplicate entities doesn't slow down the app, use more memory, interfere with method chains etc.
So, don't be afraid to use multiple seemingly redundant entities when that is the simplest solution. In Core Data, that is often the most elegant solution.
I am struggling with esactly this dilemma right now. I have many different entities in my model that can be "quantified". Say I have Apple, Pear, Farmer for all of those Entities, I need a AppleStack, PearStack, FarmerGroup, which are all just object+number. I need a generic approach to this because I want to support it in a model editor I am writing, so I decided I will define a ObjectValue abstract entity with attributes object, value. Then I will create child entities of ObjectValue and will subclass them and declare a valueEntity constant. this way I define it only once and I can write generic code that, for example, returns the possible values of the object relationship. Moreover if I need special attributes (and I actually do for a few of those) I can still add them in the child entities.

Proposed solution to NSTreeController displaying duplicate entities

As many of you may know, an NSTreeController bound to an outline view can display duplicates while presenting core data entities.
A temporary solution is to add 'parent == nil' to the predicates, but this only returns parent entities. If, for instance, a user is searching for a sub-entity, the requested sub-entity won't be displayed.
A (proposed) solution is to subclass NSTreeController and add a NSMutableSet variable, which keeps track of entities that are currently being displayed. This variable should be alloced on init, and released on dealloc.
When "fetchWithRequest:merge:error:" is called, the set should be emptied (I'm not sure whether this would be more efficient than releasing it and allocating it again). Everytime an entity is going to be added to display, check if the set contains it. If it doesn't, add it. Otherwise, find which is closer to the root (which is the subentity) and either skip it if its the subentity, or swap it with the previously included one.
I think there should be relatively little impact on performance (considering NSSet uses hashing). The problem I'm having is finding the correct method to override to add this behavior. Specifically, where NSTreeController processes fetched entities after "fetchWithRequest:merge:error:" is called.
Is it fair to say you're really looking for a way to filter the tree with a search term without losing the tree structure? The inherent problem (beyond forcing the tree controller to include the parent nodes of a search match) is that the parents may or may not actually match the search result, so it's confusing to display them.
I think yours is more a problem of UI, isn't it? In that case, the best approach (and one I've seen many well-known companies and independent developers take) is to display search results in a plain table. This way the results can be sorted by various attributes and you don't have to disable drag and drop in the outline view in search mode (to avoid the user trying to change the tree structure when only part of the tree is displayed out of context).
Expanding on Joshua's answer, I was able to implement Search Functionality into my own NSOutlineView, however it was limited to the root/parent objects in the view.
I think (like Joshua said) if you wanted to filter all objects you would have to display the results in a NSTableView.

Game positioning OO design

I'm starting a game project, my first, it'll be like a civilization clone, with a big focus in war. I always worked with C# but for business apps (mostly web apps) so I have a doubt about what would be a good design to build the map positioning system.
I would like to each unit know where it's positioned, and to the map to know all units at each point, a two-way relationship, but I can't see what would be the best way to model this! I'd like some ideas and pseudo-code, if you could!
Thankz.
Make your map a two-dimensional array. At each position, put an array of all objects at that position. In addition, add position attributes to each object.
Yes, this will duplicate the information! So on each move you'll have to change the object and update the map.
However, fast reading and fast finding of the objects is very important for that kind of game. In addition, this solution avoids any search routine (e.g. go through the map and look for a particular object), which is generally a good idea: Replace all search routines over large datasets with indexes. The map should be seen as some kind of index over the object's position attributes.
The map should have all knowledge of all object on it. Furthermore, only each object on the map should know its location. This way, the map can ask all objects where they are and place them in their correct locations. You should never have to store the positioning information twice.
Here's one approach that should avoid duplication
Have a class which holds all objects on the map, and within it collections of different types of object
public class MapObjects
{
private Collection<GamePiece> gamePieces;
}
Each item in the collections will hold its (current) map co-ordinates
public class GamePiece
{
private MapCoordinate mapCoordinate;
// Other items relevant to a GamePiece.. Health, ItemType, etc
}
To find where a particular selected item is on the map should be easy, you have a reference to the GamePiece which holds its coordinates. To find what items are in a particular coordinate you need a helper method, probably within the MapObjects class:
public class MapObjects
{
public Collection<GamePiece> GamePiecesAtLocation(MapCoordinate mapCoordinate)
{
// Iterate through gamePieces collection and build a result
// collection of items at specified coordinates.
}
}
Good luck, sounds like an interesting project with plenty of challenges.
I would make the map hexagonal instead of a grid, so you don't have the odd Civilization phenomenon where you can cover more ground diagonally. Beyond that, I would just have each unit store its own position, and when you need to know which units are in a particular hex just iterate through the whole collection. It's hard to imagine having so many units involved that this approach would be a performance problem.
NSPoint is extremely useful when it comes to things like this. Each gameobject should have it's own location. You could store these gameobjects in arrays, one for each player, one for the whole game, it's up to you.
I will warn you that this is a huge project, not only codewise, but content wise, and requires lots of back and forth work while balancing the game. You should really try a few smaller games before you go after this one. Nothing is stopping you from diving in, but you are going to hit a lot of walls and write some serious spaghetticode if your first game is something this large. I would suggest starting with something like checkers, to get the turn based side of things down.
This is all coming from the guy who is currently writing a roguelike as his first game project. In my defense it is relatively straightforward, but there are a lot of things I was not expecting, and something as simple as calculating the sight / fog of war taking obstructions into account uses complex algorithms. I don't regret picking a roguelike as my first game, but after seeing how complex even the most basic concepts can be to implement, something like a turn based strategy game is simply something I'll leave to the pros for now.
If you're currently having trouble thinking of a way to not only create the units, but represent the map and store the locations, what are you going to do when it comes time to code in research? cities? production? resource gathering? A random map generator? Trajectory calculation? Hit probability? Armor? Mobility? Line of sight? Random events? AI?
I'm not trying to crush your dreams by any means, it's just that the genre you picked is more complex than it seems. Your brain will overload and burst at the seams. (I could continue rhyming on topic, but I will refrain to remind you that you should really try something like checkers first.)
Good design = simple design.
Make the map a list of objects.
Object
int X { get; set; }
int Y { get; set; }
Map
List<Object> objects
Add(Object)
Remove(Object)
GetAt(X, Y)
GetInBox(X,Y,Width,Height)
GetInRadius(X,Y,Radius)
That should be all you need. If the Get(..) queries get too slow, add caching or divide the map into sectors and keep a list of objects for each sector and update it when they move. This helps dramatically if you have many static objects or objects that don't move too quickly from sector to sector. My guess is that in a turn-based game, you won't need to optimize at all.