Allow User to Save Generated Array String for Later Viewing - objective-c

I'm creating a small app that generates baby names from 2 separate NSArrays. I have 1 setup for first name and 1 setup for middle name. When the button is pushed it concatenates 2 NSStrings at random as seen with this code:
int a = arc4random() % 2;
int b = arc4random() % 2;
// populate the array for the names
NSArray *firstNameArray = [NSArray arrayWithObjects: #"Anna",
#"Amy",
#"Amber", nil];
NSArray *middleNameArray = [NSArray arrayWithObjects: #"Brenda", #"Beatrix", nil];
// concatenate strings at index of array
NSString *fullName = [NSString stringWithFormat:#"%# %#", [firstNameArray objectAtIndex:a], [middleNameArray objectAtIndex:b]];
// display the newly created first & middle names
babyname.text = fullName;
I'm kind of at a loss for how to allow a user to 'favorite' a particular name and save it to a new view (probably table view). Can anyone point me in the right direction here?

What you would probably want to do is store the names selected so that you could refer to them later. You may wish to create a Person class or something of the like and have a property in it called favorite which is a BOOL value. Then you would just have to set the favorite property to YES for the ones the user wants to favorite.
A good mechanism to store a custom class and have it persist is Core Data, but it really depends on how many Person instances you will/could have. Core Data is really easy to implement once you get the hang of it and there are many tuorials online of how to use it. I would check out the iTunesU videos from Stanford on CoreData using UIDocument and UIManagedDocument. I found them very helpful.
Good Luck.

You have given a snippet of your code from which the exact flow of your logic in your program is incomprehensible , assuming that u have a textfield for user to input and a button to mark it as favorite then in the action of button you can get the text from textfield and store it in some array .Moreover you don't store data in tableview but you display it there.You can then use the Favorited array to display the names in a tableview .
You can use NSUserDefaults,plist,sqlite,coredata for persistent storage.
NSUserDefaults and plist can handle only low amount data efficiently.
Please See My Link on
persistent storage
Tutorial on TableView

Related

Why isn't the name property of my NSImage being copied when I call `-copy`?

I have an NSArray ("objects") that contains objects of type NSImage
I have found that when I try to make a copy of each image in the array, the name property on the NSImage does not get copied.
for (NSObject* object in objects)
{
NSMenuItem* menuItem = nil;
if ([object isKindOfClass:[NSImage class]])
{
NSImage* image = [object copy];
//Breakpoint here
Here is a screenshot of my variable view at the breakpoint above ^^
How could it be that the name property isn't being copied?
Name on images is used as a special registration mechanism so you can look the images up by name later. As such you can only have one image with each name. If you change the name on an image then the original registration is removed and the new one added. If an image already have the name you try to set then the set is declined.
Effectively what you're seeing is an attempted re-registration of an image name against a different image. That image might be a copy, so you might think it's fine to keep the name, but you don't know what the private implementation is and you also aren't considering potential mutable subclasses.
So, you can't share names across multiple different images. If you want to do something similar then you need to manage the names / identifiers separately using a custom scheme / approach.

Suggestions to Process Complex + Large Data File

I have a very large and complex data file (.txt, see snippet below) of about 10MB and would like to know the best way to store it and access it later on.
My app currently uses core data for storage of other entities but I don't see how I can create an entity from this type of data file because of its complexity.
This file is divided as follows:
First line of each major section begins with an A| and means a new 'airway' to be defined. Then, is it's name, so in the example below we have the airway named V320 and another named V321. On the following lines, we have important data, the 'points'/waypoints which make up this airway. Each one has a name, and coordinates. So the first one here is PLN at 45.63N and -84.66W (coordinates). Then, from there the next one is LORIW at 45.35N and -84.92W, from LORIW we go to IROTO, and so on...
NOTE: There may be two, three, maybe even 4 airways with the same 'name' like V320 for example has 3...but each one is in it's own part of the map.
The other values there are irrelevant such as the numbers after the coordinate pair.
In essence, I need all this so that I can then draw lines on my map (GMSPolyLine using Google map SDK) which goes through all these points for each airway and then to create GMSMarkers(google version of MKAnnotation) for each waypoint which the user can tap.
I can handle the drawing of lines/markers on the map but the difficult part for me to visualize is the manipulation of this data and making it easier to access.
Let me know if you have any questions.
A|V320|20
S|PLN|045630647|-0084664108|LORIW|045352072|-0084924214|0|219|1998
S|LORIW|045352072|-0084924214|IROTO|045188989|-0085075111|219|219|1168
S|IROTO|045188989|-0085075111|ADENO|045030644|-0085220425|219|219|1132
S|ADENO|045030644|-0085220425|TIDDU|044877978|-0085359767|215|215|1090
S|TIDDU|044877978|-0085359767|SKIPR|044831714|-0085401772|215|215|330
.....
A|V321|29
S|PZD|031655206|-0084293100|KUTVE|031866950|-0084451303|0|329|1505
S|KUTVE|031866950|-0084451303|DUVAT|031948772|-0084512695|329|329|582
S|DUVAT|031948772|-0084512695|LUMPP|032041158|-0084582139|329|329|657
S|LUMPP|032041158|-0084582139|PREST|032176375|-0084684117|329|329|963
S|PREST|032176375|-0084684117|CSG|032615253|-0085017631|326|326|3129
S|CSG|032615253|-0085017631|JALVO|032722436|-0085064033|326|339|684
.....
Your data exhibits some regularity. If it is predictable and consistent, just write a parser that iterates through the file and creates appropriate Core Data entities.
For example, the fact that each new airway is separated by a newline can help you find those. Also, each final waypoint is repeated in the next line unless you are at the end of an airway record. I think you can do this in maybe 20-30 lines of code.
On your development machine (or even on an iPad or recent iPhone, for that matter), even creating a 10MB array in memory (to be parsed) should not be a constraint.
If the data is static, you can use the resulting sqlite database as a read-only persistent store that you can include in your app bundle.
As for the parser, it would be something like this:
NSString *file = [[NSString alloc] initWithContentsOfFile:fileURLString
encoding:NSUTF8StringEncoding error:nil];
NSArray *lines = [file componentsSeparatedByString:#"\n"];
for (NSString *line in lines) {
if (line.length < 1) { continue; }
NSArray *fields = [line componentsSeparatedByString:#"|"];
if ([fields.firstObject isEqualToString:#"A"]) {
// insert new airway object and populate with other fields
}
else if ([fields.firstObject isEqualToString:#"S"]) {
// insert new waypoint object (two for each first line)
// assign as relationship to the current airway
// and to another waypoint as necessary
}
}
[managedObjectContext save:nil];

Objective-C: how to compare 2 PLists

I'm a total newbie to Objective-C and have been tasked with an assignment to compare 2 builds of same app for differences in their Info.plist and Defaults.plist.
I have been able to figure out the steps to read the PLists from app bundle but am having difficulty figuring out how to compare EVERY key in PLists to its counterpart file. For illustration if I need to compare Info.plist between 2 app bundle (lets say build_100 and build_101), how do I recursively go to each key in build_100 and compare the same key in build_101 to verify if they are same or not.
Its easy if both PLists are same because isEqualToDictionary will return TRUE but problem occurs if something in a nested dictionary is different between both the builds.
Going through related queries here, it clear to me that the answer is that I write a recursive method that iterates through both PLists but I'm having a real frustrating time to figure out a way to do this for a nested dictionary like Info.plist.
So I've finally figured this thing out so thought of sharing it with others for future reference. I'm sure there'll be some other lost soul in future looking for something similar (or at least I hope :)).
The way I wrote my code was to:
Read both Plists in NSDictionaries
Treat one Plist as "to be tested" and other as the reference (to compare against) to find out if its a Pass/Fail
Loop through all keys in "to be tested" Plist and compare each one of them in "reference" Plist
When it came to compare an Array or Dictionary, this check (that's the part I was struggling with) had to be a recursive check
The code to write for step #1, 2, 3 is straight forward so I'm going to give the method I wrote for #4 which was the crux of my original question.
This function compareSourceObject() will take 3 arguments:
sourceObject: object to be tested
targetObject: object to compare against
trailPath: string that'll hold the entire path of the key that has failed
- (void)compareSourceObject:(id)sourceObject andTargetObject:(id)targetObject withBreadcrumbTrail:(NSString *)trailPath{
NSString *message = [[NSString alloc] init];
if ([sourceObject isKindOfClass:[NSDictionary class]]){
for(id item in sourceObject){
[self compareSourceObject:[sourceObject objectForKey:item] andTargetObject:[targetObject objectForKey:item] withBreadcrumbTrail:[trailPath stringByAppendingFormat:#"->%#", item]];
}
}
else if ([sourceObject isKindOfClass:[NSArray class]]){
for (int counter=0; counter %d", counter]];
}
}
else if(![sourceObject isEqual:targetObject]){
NSLog(#"Values do not match. Value in \"TestedDicationary\" is (%#) but the reference dict has (%#)", targetObject, sourceObject);
}
}
Hope this helps. Comments/Suggestions/Optimizations are more than welcome.
Take one plist, and interpret the properties as a set (NSSet) of string values, e.g.
:items:0:assets array
:items:0:assets:0:kind string VALUE
Note I am using /usr/libexec/PlistBuddy format to describe a property - path type [value].
Then do the same for the second plist and compare the sets using NSSet functions.

Why does accessing my NSMutableArray become faster once I've added more objects to it?

Something very odd is going on. I populate my array as follows:
self.workingWithItemCollectionArray = [NSMutableArray arrayWithCapacity:self.itemCollectionArray.count];
self.workingWithItemCollectionArray = [[self.itemCollectionArray mutableCopy]autorelease];
It take a mutable copy of the original NSArray and pass it to the NSMutableArray. When accessing the information contained in this array by the click of a UIButton, there is a slight delay in retrieving the information.
But when I then change the original array to add more items, and then pass this onto the mutable array:
NSMutableArray *editedOriginalArray = [NSMutableArray arrayWithArray:self.itemCollectionArray];
[editedOriginalArray addObjectsFromArray:extraObjectsToAdd];
self.itemCollectionArray = [NSArray arrayWithArray:editedOriginalArray];
self.workingWithItemCollectionArray = [NSMutableArray arrayWithCapacity:self.itemCollectionArray.count];
self.workingWithItemCollectionArray = [[self.itemCollectionArray mutableCopy]autorelease];
It is then after this that I am able to press the button and information is accessed instantly (whereas before the button would stay pressed for a very short time).
Any ideas on why this could be?
It has to do with how NSMutableArray is implemented vs NSArray.
Because NSArray is immutable, the objects are literally internally stored in an array, e.g.:
id *objects = malloc(sizeof(id) * count);
However, when you deal with NSMutableArray, you are dealing with instead, a linked list, as NSMutableArray expects many modifications on the array. So, the lookup on a linked list is much longer, because your objects are not stored in a way where there is a set distance in memory between them.
For more information on linked lists, check here.

How does one save a list of images in Objective-C

In my code I have an item that is a list of alternating strings and images that I wish to save. I know how to save individual images in their JPEG representations, but is there a simple and efficient way I don't know of in Objective-C to save all these items (or at least the images since I can handle the strings myself) while maintaining their order?
ex: item 1 ("hi", image, "how", image, "are", image), item2("this", image, "is", image)
maintaining item order is not important to me, but the order in the list is. The first thing that comes to mind is simply to save every single image, and have an algorithm to create then remember their imagename and then save and load the text list. Is there an easier way to do this? Can I literally just save the array itself as a plist and be on my merry way? (i've only seen examples of these with strings)
I believe I understand what you're going for. You'd like to save an array of items, each of which contains an array of Objects that contain an image and a string. If this is accurate then you're idea of saving the array to a plist is correct.
In short you would create NSDictionaries of your Objects and save the array of them. Like so:
In your object you'll have a method similar to this:
- (NSDictionary *)dictionaryOfItemData;
{
NSMutableDictionary * mutableDictionary = [[NSMutableDictionary alloc] init];
[mutableDictionary setObject:imageName
forKey:#"imageName"];
[mutableDictionary setObject:UIImagePNGRepresentation([self image])
forKey:#"imageData"];
return mutableDictionary;
}
Then you would save an array of these (or array of arrays, or whatever your desire based on file size concerns, need to load, etc.) like so in the proper place:
[[arrayOfDictionaries description] writeToFile:path
atomically:YES
encoding:NSUTF8StringEncoding
error:NULL];
Which gives you the plist, that you can load and hydrate by creating your image with data and setting the image name from the dictionary.
~Good Luck