How to get first value from NSMutableArray (iPhone)? - iphone

Now i am working in simple iphone application, i have stored some value in NSMutableArray like "{54.399, 196}","{-268.246, 273}".so i want to get 54.399 in first indexpath, how to get this, please help me
Thanks in Advance

It seems you have an Array of Arrays, so it would be:
[[myArray objectAtIndex:0] objectAtIndex:0];
Or using subscripting:
myArray[0][0];
Edit:
Ok you have an Array of NSStrings. To do what you want (get the 53.399) do the following:
NSString *myString = [myArray objectAtIndex:0];
NSArray *stringComponents = [myString componentsSeparatedByString:#","];
NSString *myFinalString = [stringComponents objectAtIndex:0];
With subscripting:
NSString *myFinalString = [[myArray[0] componentsSeparatedByString:#","][0];

You can use
[[arrayObj objectAtIndex:0] objectAtIndex:0];

Related

Saving Array To File Objective C

I've been stuck on this for ever and I finally figured it out and now just out of the blue it stopped working again...
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/scoreCards.dgs",documentsDirectory];
NSMutableArray *savedArrayOfScorecards = [[NSMutableArray alloc]init];
savedArrayOfScorecards = [NSMutableArray arrayWithContentsOfFile:filePath];
[savedArrayOfScorecards addObject:currentScoreCard];
[savedArrayOfScorecards writeToFile:filePath atomically:YES];
The file scoreCards.dgs is not even getting created...
What am I doing wrong?
There could be a couple things going wrong here.
1) The kind of data you're storing in the array might not be encodable or archive-able to a file. And the code snippet you included doesn't give a good hint as to what kind of data you're trying to save. If you have custom objects in your array (i.e. things that are not NSString, NSNumber, NSDate, etc.), then that's definitely the problem. There are plenty of questions here on StackOverflow that might help you solve this issue.
2) Your array's filepath could be bogus. For example, you're not checking to see if "documentsDirectory" is nil or valid or writeable.
3) Also possible, but not likely, "savedArrayOfScorecards" might be a nil array. You should do error checking to make sure "savedArrayOfScorecards" was instantiated and that there is more than one object in the array.
Your problem is, that although you create an array, before reading the file it is getting nil-ed on your call to:
savedArrayOfScorecards = [NSMutableArray arrayWithContentsOfFile:filePath];
So, because this savedArrayOfScorecards is now nil, your call to write it to a file is not doing anything.
You should load the array to another variable, and check it being nil, and create the new array only if the one read from the file is nil. Something like this:
NSMutableArray *savedArrayOfScorecards = [NSMutableArray arrayWithContentsOfFile:filePath];
if (!savedArrayOfScorecards) {
savedArrayOfScorecards = [[NSMutableArray alloc]init];
}
Are you sure the file exists when loading it?
savedArrayOfScorecards = [NSMutableArray arrayWithContentsOfFile:filePath];
This line creates a new NSMutableArray from the file. If the file does not exist, it returns nil. writeToFile is then sent to nil and nothing would happen.
Add a check to see if it's nil and create a new array if it is:
NSMutableArray *savedArrayOfScorecards = [NSMutableArray arrayWithContentsOfFile:filePath];
if(savedArrayOfScorecards == nil) savedArrayOfScorecards = [NSMutableArray array];
[savedArrayOfScorecards addObject:currentScoreCard];
[savedArrayOfScorecards writeToFile:filePath atomically:YES];
NSMutableArray is not a property-list-compliant format. You must use an NSArchiver to make it plist compliant.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/scoreCards.dgs",documentsDirectory];
NSMutableArray *savedArrayOfScorecards = [[NSMutableArray alloc]init];
savedArrayOfScorecards = [NSMutableArray arrayWithContentsOfFile:filePath];
[savedArrayOfScorecards addObject:#"ALLLAALLAAALLA"];
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archive = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
[archive encodeObject:savedArrayOfScorecards forKey:#"Scorecards"];
[archive finishEncoding];
BOOL result = [data writeToFile:filePath atomically:YES];
NSLog(result ? #"YES" : #"NO");
The correct answers are already here, just adding a better solution:
NSFileManager* fileManager = [NSFileManager defaultManager];
NSMutableArray* array;
if ([fileManager fileExistsAtPath:filePath]) {
array = [NSMutableArray arrayWithContentsOfFile:filePath];
NSAssert(array != nil, #"Invalid data in file.");
}
else {
array = [[NSMutableArray] alloc] init];
}
[array addObject:currentScoreCard];
[array writeToFile:filePath atomically:YES];

I need to combine two NSArray/NSDictionaries together

I have two plist files that I'm using as datasources to create NSArray and NSDictionaries in my app.
I want the output of the CSV file to look like:
exerciseName, muscleGroup, description
Barbell Curl, Biceps, This is a bicep exercise
The problem is, I need to first combine two NSDictionaries I have. One has exerciseName and muscleName, while the other has exerciseDescription. But I need to have one array of dictionaries for each exercise obejct that has all 3 keys.
I'm using the following code to build the main NSMutableArray
if (muscleArray == nil)
{
NSString *path = [[NSBundle mainBundle]pathForResource:#"data" ofType:#"plist"];
NSMutableArray *rootLevel = [[NSMutableArray alloc]initWithContentsOfFile:path];
self.muscleArray = rootLevel;
}
NSMutableArray *arrayForSearching = [NSMutableArray array];
for (NSDictionary *muscleDict in self.muscleArray)
for (NSDictionary *excerciseDict in [muscleDict objectForKey:#"exercises"])
[arrayForSearching addObject:[NSDictionary dictionaryWithObjectsAndKeys:
[excerciseDict objectForKey:#"exerciseName"], #"exerciseName",
[muscleDict objectForKey:#"muscleName"], #"muscleName", nil]];
self.exerciseArray = arrayForSearching;
I'm using the following code to build the NSDictionary which has the exerciseDescription key
NSString *exerciseNameString =self.exerciseName;
NSString *path = [[NSBundle mainBundle] pathForResource:#"ExerciseDescriptions" ofType:#"plist"];
NSDictionary *exerciseDescription = [NSDictionary dictionaryWithContentsOfFile:path];
NSString *description = [exerciseDescription objectForKey:exerciseNameString];
You obviously know how to iterate through and create dictionaries, so what's the problem?
Iterate through exerciseArray and add an exercise description to each of its dictionaries. However this seems wildly inefficient and you should probably rethink the whole thing. Why not store them on disk in a ready-to-use format?
Arrays are used when the order of items matters. It doesn't seems to really matter here, so why not just keep them as NSDictionaries? If you need to access all keys in a dictionary just call allKeys
EDIT: Like this?
NSString *path = [[NSBundle mainBundle] pathForResource:#"ExerciseDescriptions"
ofType:#"plist"];
NSDictionary *descriptions = [NSDictionary dictionaryWithContentsOfFile:path];
NSMutableArray *exercises = self.exerciseArray;
for (NSInteger i = 0; i < [exercises count]; i++) {
NSMutableDictionary *dict = [[exercises objectAtIndex:i] mutableCopy];
NSString *name = [dict valueForKey:#"exerciseName"];
NSString *desc = [descriptions valueForKey:name];
if (desc) {
[dict setValue:desc forKey:#"exerciseDescription"];
[exercises replaceObjectAtIndex:i withObject:dict];
}
[dict release];
}
I created the following project to address my need to merge two dictionaries created from plists:
https://github.com/bumboarder6/NSDictionary-merge
It works even if you have some duplicate entries between your two dictionaries or arrays and it also recursively merges so you get a merge of your whole plist even when it contains dictionaries of dictionaries of arrays of dictionaries (etc.).

parsing text file in objective C

i am trying to parse a text file saved in doc dir below show is the code for it
NSArray *filePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *docDirPath=[filePaths objectAtIndex:0];
NSString *filePath=[docDirPath stringByAppendingPathComponent:#"SKU.txt"];
NSError *error;
NSString *fileContents=[NSString stringWithContentsOfFile:filePath];
NSLog(#"fileContents---%#",fileContents);
if(!fileContents)
NSLog(#"error in reading file----%#",error);
NSArray *values=[fileContents componentsSeparatedByString:#"\n"];
NSLog(#"values-----%#",values);
NSMutableArray *parsedValues=[[NSMutableArray alloc]init];
for(int i=0;i<[values count];i++){
NSString *lineStr=[values objectAtIndex:i];
NSLog(#"linestr---%#",lineStr);
NSMutableDictionary *valuesDic=[[NSMutableDictionary alloc]init];
NSArray *seperatedValues=[[NSArray alloc]init];
seperatedValues=[lineStr componentsSeparatedByString:#","];
NSLog(#"seperatedvalues---%#",seperatedValues);
[valuesDic setObject:seperatedValues forKey:[seperatedValues objectAtIndex:0]];
NSLog(#"valuesDic---%#",valuesDic);
[parsedValues addObject:valuesDic];
[seperatedValues release];
[valuesDic release];
}
NSLog(#"parsedValues----%#",parsedValues);
NSMutableDictionary *result;
result=[parsedValues objectAtIndex:1];
NSLog(#"res----%#",[result objectForKey:#"WALM-FT"]);
The problem what i am facing is when i try to print lineStr ie the data of the text file it is printing as a single string so i could not able to get the contents in line by line way please help me solve this issue.
Instead use:
- (NSArray *)componentsSeparatedByCharactersInSet:(NSCharacterSet *)separator
it covers several different newline characters.
Example:
NSArray *values = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
for (NSString *lineStr in values) {
// Parsing code here
}
ALso seperatedValues is over released. First one is created with alloc init, then on the next line it is replaced by the method componentsSeparatedByString. So the first one od lost without being released, that is a leak. Later the seperatedValues created by componentsSeparatedByString is released but it is already auto released by componentsSeparatedByString to that is an over release;
Solve all the retain/release/autorelease problem with ARC (Automatic Reference Counting).
Here is a version that uses convenience methods and omits over release:
NSArray *values = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
for (NSString *lineStr in values) {
NSArray *seperatedValues = [lineStr componentsSeparatedByString:#","];
NSString *key = [seperatedValues objectAtIndex:0];
NSDictionary *valuesDic = [NSDictionary dictionaryWithObject:seperatedValues forKey:key];
[parsedValues addObject:valuesDic];
}
NSLog(#"parsedValues---%#",parsedValues);
Are you sure the line separator used in your text file is \n and not \r (or \r\n)?
The problem may come from this, explaining why you don't manage to split the files into different lines.

How to selectively trim an NSMutableString?

I would like to know how to selectively trim an NSMutableString. For example, if my string is "MobileSafari_2011-09-10-155814_Jareds-iPhone.plist", how would I programatically trim off everything except the word "MobileSafari"?
Note : Given the term programatically above, I expect the solution to work even if the word "MobileSafari" is changed to "Youtube" for example, or the word "Jared's-iPhone" is changed to "Angela's-iPhone".
Any help is very much appreciated!
Given that you always need to extract the character upto the first underscore; use the following method;
NSArray *stringParts = [yourString componentsSeparatedByString:#"_"];
The first object in the array would be the extracted part you need I would think.
TESTED CODE: 100% WORKS
NSString *inputString=#"MobileSafari_2011-09-10-155814_Jareds-iPhone.plist";
NSArray *array= [inputString componentsSeparatedByString:#"_"];
if ([array count]>0) {
NSString *resultedString=[array objectAtIndex:0];
NSLog(#" resultedString IS - %#",resultedString);
}
OUTPUT:
resultedString IS - MobileSafari
If you know the format of the string is always like that, it can be easy.
Just use NSString's componentsSeparatedByString: documented here.
In your case you could do this:
NSString *source = #"MobileSafari_2011-09-10-155814_Jareds-iPhone.plist";
NSArray *seperatedSubStrings = [source componentsSeparatedByString:#"_"];
NSString *result = [seperatedSubStrings objectAtIndex:0];
#"MobileSafari" would be at index 0, #"2011-09-10-155814" at index 1, and #"Jareds-iPhone.plist" and at index 2.
Try this :
NSString *strComplete = #"MobileSafari_2011-09-10-155814_Jareds-iPhone.plist";
NSArray *arr = [strComplete componentsSeparatedByString:#"_"];
NSString *str1 = [arr objectAtIndex:0];
NSString *str2 = [arr objectAtIndex:1];
NSString *str3 = [arr objectAtIndex:2];
str1 is the required string.
Even if you change MobileSafari to youtube it will work.
So you'll need an NSString variable that'll hold the beginning of the string you want to truncate. After that one way could be to change the string and the variable string values at the simultanously. Say, teh Variable string was "Youtube" not it is changed to "MobileSafari" then the mutable string string should change from "MobileSafari_....." to "YouTube_......". And then you can get the variable strings length and used the following code to truncate the the mutable string.
NSString *beginningOfTheStr;
.....
theMutableStr=[theMutableStr substringToIndex:[beginningOfTheStrlength-1]];
See if tis works for you.

Why doesen't it work to write this NSMutableArray to a plist?

edited.
Hey, I am trying to write an NSMutableArray to a plist.
The compiler does not show any errors, but it does not write to the plist anyway.
I have tried this on a real device too, not just the Simulator.
Basically, what this code does, is that when you click the accessoryView of a UITableViewCell, it gets the indexPath pressed, edits an NSMutableArray and tries to write that NSMutableArray to a plist. It then reloads the arrays mentioned (from multiple plists) and reloads the data in a UITableView from the arrays.
Code:
NSIndexPath *indexPath = [table indexPathForRowAtPoint:[[[event touchesForView:sender] anyObject] locationInView:table]];
[arrayFav removeObjectAtIndex:[arrayFav indexOfObject:[NSNumber numberWithInt:[[arraySub objectAtIndex:indexPath.row] intValue]]]];
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:#"arrayFav.plist"];
NSLog(#"%# - %#", rootPath, plistPath);
[arrayFav writeToFile:plistPath atomically:YES];
// Reloads data into the arrays
[self loadDataFromPlists];
// Reloads data in tableView from arrays
[tableFarts reloadData];
CFShow() on the array after removing one of them shows this:
<CFArray 0x6262110 [0x2c810a0]>{type = mutable-small, count = 4, values = (
0 : <CFNumber 0x6502e10 [0x2c810a0]>{value = +3, type = kCFNumberSInt32Type}
1 : <CFNumber 0x6239de0 [0x2c810a0]>{value = +8, type = kCFNumberSInt32Type}
2 : <CFNumber 0x6239dc0 [0x2c810a0]>{value = +10, type = kCFNumberSInt32Type}
3 : <CFNumber 0x6261420 [0x2c810a0]>{value = +40, type = kCFNumberSInt64Type}
DEBUG-INFO: writeToPlist shows YES, I have tried to release all the arrays before filling them up again, setting them to nil, set atomically to NO.
As discussed in the comments below, the actual problem here is that the plist is being read from and written to two different locations. Somewhere in the app, there is code that reads the file into the array similar to this:
NSString *plistFavPath = [[NSBundle mainBundle] pathForResource:#"arrayFav"
ofType:#"plist"];
arrayFav = [[NSMutableArray alloc] initWithContentsOfFile:plistFavPath];
This logic reads the array from the application's bundle, which is a read-only location and part of the distributed app. Later when the edited array is persisted, code similar to this is used:
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES) objectAtIndex:0];
NSString *plistPath = [rootPath
stringByAppendingPathComponent:#"arrayFav.plist"];
NSLog(#"%# - %#", rootPath, plistPath);
[arrayFav writeToFile:plistPath atomically:YES];
The result here is that the updated file gets written to the app's documents directory, but it is never read from there, giving the appearance that the file is not being saved correctly. To correct this, you should change the code that reads the file to use the same path that you are writing to.
If you need to distribute a default version of the plist for use on the initial launch before the array has been edited, you could continue to include a version of the file in your bundle and then add code to your app delegate that check if the file exists in the documents directory and if it is not present, copies the bundle's default version of the file to the proper place.
[yourMutableArray writeToFile:fileName atomically:YES];
This should work. NSMutableArray inherits from NSArray which has a method to write to a plist.
writeToFile:atomically: won't work if your array contains custom objects.
If your array contains custom objects that are not Plist objects (NSArray, NSDictionary, NSString, NSNumber, etc), then you will not be able to use this method. This method only works on Plist objects.
Another option would be to use the NSCoding protocol, and write your objects to disk that way.
Yes
Look at the Property List Programming Guide.
phoneNumbers is a NSMutableArray
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
NSString *error;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:#"Data.plist"];
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects:
[NSArray arrayWithObjects: personName, phoneNumbers, nil]
forKeys:[NSArray arrayWithObjects: #"Name", #"Phones", nil]];
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict
format:NSPropertyListXMLFormat_v1_0
errorDescription:&error];
if(plistData) {
[plistData writeToFile:plistPath atomically:YES];
}
else {
NSLog(error);
[error release];
}
return NSTerminateNow;
}