Reading from NSMutableArray throws exception at item 2 even though it exists - iphone

I've got a file with a bunch of string in like so:
item1,01-SR,admin,Missing or broken,undefined, 16/04/2013 18:10:10;
item1,03-SR,admin,In Use,undefined, 16/04/2013 18:10:34;
item1,01-SR,admin,In Use,undefined, 16/04/2013 18:10:45;
item1,02-SR,admin,In Use,undefined, 16/04/2013 18:10:49;
item1,05,admin,In Use,undefined, 16/04/2013 18:10:56;
I'm reading the strings in and then splitting them up so I just get one string at a time. Then I want to split up the string I've got again so each CSV is it's own variable. I've tried this like so (numLines is a count of the number of lines in the file):
while (count1 < numLines) {
NSString *message = [[strings objectAtIndex: count1] copy];
NSMutableArray *items = [[fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#";"]] mutableCopy];
NSString *items1 = [[items objectAtIndex: count1] copy];
NSLog(#"items: %#", items1);
NSMutableArray *inditems = [[items1 componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#","]] mutableCopy];
NSString * item1 = inditems[0];
NSString * bnum1 = inditems[1];
NSString * user1 = inditems[2];
NSString * state1 = inditems[3];
NSString * gender1 = inditems[4];
NSString * tstamp1 = inditems[5];
NSLog(#"item: %#", item1);
NSLog(#"bnum: %#", bnum1);
NSLog(#"user: %#", user1);
NSLog(#"state: %#", state1);
NSLog(#"gender: %#", gender1);
NSLog(#"tstamp: %#", tstamp1);
count1++;
}
Now, this works as far as selecting one line from the file and it puts the first two items into the array and then writes the values of item1 and bnum1 to the log but then it throws an exception for some reason. Now this would usually suggest to me that item 2 doesn't exist in the array so I did a count like so:
NSLog(#"count = %d", [inditems count]);
Which correctly returns 6. I then wanted to check that it could actually read another item from the array so I did:
NSString *tstamp1 = [[inditems lastObject] copy];
Which when logged correctly returns the time stamps like so:
16/04/2013 18:10:10
So I thought "oh at least item 5 works" and tried just getting that item:
while (count1 < numLines) {
NSString *message = [[strings objectAtIndex: count1] copy];
NSMutableArray *items = [[fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#";"]] mutableCopy];
NSString *items1 = [[items objectAtIndex: count1] copy];
NSLog(#"items: %#", items1);
NSMutableArray *inditems = [[items1 componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#","]] mutableCopy];
NSString * item1 = inditems[0];
NSString * bnum1 = inditems[1];
NSString * tstamp1 = inditems[5];
NSLog(#"item: %#", item1);
NSLog(#"bnum: %#", bnum1);
NSLog(#"tstamp: %#", tstamp1);
count1++;
}
But that also throws an exception! I'm probably doing something stupid here, but I would appreciate any help.
Thanks!

My guess is your NSArray *strings is including empty value which is causing your error. You need to check it first and then do your logic.
//path is your file path
NSString* fileContents = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
NSArray *strings = [fileContents componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
for (int i = 0; i < [strings count]; i++){
if (![[strings objectAtIndex:i] isEqualToString:#""]){
//Here do your code...
}
}

Related

Extracting Unique Objects from a Data Array

I want to add names in a data array only if the name does not previously exist in the data array. When I attempt to print these names, I do get repetitions. Is there a way to solve this?
-(NSMutableArray *)autoComplete
{
NSMutableArray *dataArray = [[NSMutableArray alloc] init];
NSString *url = [NSString stringWithFormat:#"%#45.25,-95.25&limit=100&client_id=Von0J4Bu6INiez5bGby2R&client_secret=50sUjSbg7dba8cQgtpdfr5Ns7wyYTqtmKpUU3khQ",kWSURL];
NSDictionary * returnDict = (NSDictionary *) [self callWebService:url];
if([returnDict objectForKey:#"success"])
{
NSArray *responceArray = [returnDict objectForKey:#"response"];
for (NSDictionary *dict in responceArray) {
placeDC *place = [[placeDC alloc]init];
NSDictionary *placeDict = (NSDictionary *)[dict objectForKey:#"place" ];
NSDictionary *loctionDict =(NSDictionary *)[dict objectForKey:#"loc"];
NSString * name =[placeDict objectForKey:#"name"];
NSString * stateFull =[placeDict objectForKey:#"stateFull"];
NSString * countryFull =[placeDict objectForKey:#"countryFull"];
NSString *latitude =[loctionDict objectForKey:#"lat"];
NSString *longitude = [loctionDict objectForKey:#"long"];
place.placeNmae=name;
place.countryFullName=countryFull;
place.stateFullName=stateFull;
NSLog(#"%# ",stateFull);
place.latitude=[latitude doubleValue];
place.longitude=[longitude doubleValue];
[dataArray addObject:place];
}
}
return dataArray;
}
First Check that is there any response from the Server side or not, to check response use NSLog() or Break Points.
if response is ok then put a the following check your code
if (![dataArray containsObject:#"Some Name"])
{
// add Object
}
You could add the name NSString to an NSSet and check in every cycle whether it contains it or not.
Inside your if you could write something like:
NSArray *responceArray = [returnDict objectForKey:#"response"];
NSSet *names = [[NSSet alloc] init];
for (NSDictionary *dict in responceArray) {
NSDictionary *placeDict = (NSDictionary *)[dict objectForKey:#"place" ];
NSString * name =[placeDict objectForKey:#"name"];
if (![names containsObject:name]) {
[names addObject:name];
placeDC *place = [[placeDC alloc]init];
NSDictionary *loctionDict =(NSDictionary *)[dict objectForKey:#"loc"];
NSString * stateFull =[placeDict objectForKey:#"stateFull"];
NSString * countryFull =[placeDict objectForKey:#"countryFull"];
NSString *latitude =[loctionDict objectForKey:#"lat"];
NSString *longitude = [loctionDict objectForKey:#"long"];
place.placeNmae=name;
place.countryFullName=countryFull;
place.stateFullName=stateFull;
NSLog(#"%# ",stateFull);
place.latitude=[latitude doubleValue];
place.longitude=[longitude doubleValue];
[dataArray addObject:place];
}
}
Hope this helps!
Do one thing, add your dict in another array and search in this array that data already exist or not,
[tempAry addObject: dict];
and before insertion
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == %#", name];
NSArray *filteredArray = [tempAry filteredArrayUsingPredicate:predicate];
if ([filteredArray count] == 0)
{
[dataArray addObject:place];
}
else{
//Already exist
}
Why don't you create a separate dictionary, as an ivar or property of you class, for storing our required value, say it as :
NSMutableDictionary *uniqueValueDict=[NSMutableDictionary new];
And keep storing your required value and key as:
[uniqueValueDict setObject:stateFull forKey:uniqueValueDict];
Your work will be done.
This is the easiest solution that i have applied and this should get you going in picking up unique elements out of array.
NSArray * claimedOfferArray = [[NSArray alloc]initWithObjects:#"A",#"B",#"A",#"C",#"B" nil];
NSArray * distinctArray = [[NSArray alloc]init];
distinctArray =[[NSSet setWithArray:claimedOfferArray] allObjects];
This code will also work with NSMutableArray
Let me know if it works for you..:).

Convert String into special - splitting an NSString

I have a string like: "mocktail, wine, beer"
How can I convert this into: "mocktail", "wine", "beer"?
the following gives you the desired result:
NSString *_inputString = #"\"mocktail, wine, beer\"";
NSLog(#"input string : %#", _inputString);
NSLog(#"output string : %#", [_inputString stringByReplacingOccurrencesOfString:#", " withString:#"\", \""]);
the result is:
input string : "mocktail, wine, beer"
output string : "mocktail", "wine", "beer"
You need to use:
NSArray * components = [myString componentsSeparatedByString: #", "];
NSString *string = #"mocktail, wine, beer";
//remove whitespaces
NSString *trimmedString = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
//get array of string
NSArray *array = [trimmedString componentsSeparatedByString:#","];
NSMutableArray *newArray = [[NSMutableArray alloc] init];
for (NSString *trimmedString in array) {
NSString *newString = [NSMutableString stringWithFormat:#"'%#'", trimmedString];
[newArray addObject:newString];
}
//merge new strings
NSString *finalString = [NSString stringWithFormat:#"%#", [newArray objectAtIndex:0]];
for (NSInteger i = 1; i < [newArray count]; i++) {
finalString = [NSString stringWithFormat:#"%#, %#", finalString, [newArray objectAtIndex:i]];
}
Without knowing spesifically about iOS or objective-c, I assume you could use a split function.
In almost any higher level programming language there is such a function.
Try:
Objective-C split
This gets you an array of Strings. You can then practically do with those what you want to do, e.g. surrounding them with single quotes and appending them back together. :D

Xml parsing in Iphone and adding values to NSMutableArray

I am new to xml parsing. I have the following xml
<myMainList>
<mySubList>
<edited>true</edited>
<mySharedNumber>W59QYBZKJ4</mySharedNumber>
</mySubList>
<mySubList>
<edited>false</edited>
<mySharedNumber>TOW4KLP9WD</mySharedNumber>
</mySubList>
<mySubList>
<edited>true</edited>
<mySharedNumber>XH8JDIZA64</mySharedNumber>
</mySubList>
<mySubList>
<edited>false</edited>
<mySharedNumber>V2YOHSNODT</mySharedNumber>
</mySubList>
</myMainList>
I have edited my question.
I am not familiar with looping through the whole xml and adding the values into my array. Can someone show me how I can add the 4 sharedNumberList values into my array.
Edit:
GDataXMLElement *node;
NSArray * array = [node nodesForXPath:#"//return/myMainList/mySubList" error:nil];
NSLog(#"count :%d",[array count]);
int sharedContacts = [array count];
NSMutableArray *mySharedListArray = [[NSMutableArray alloc]init];
for(int i = 1; i<= sharedContacts; i++){
NSString *xmlDataFetcher = [NSString stringWithFormat:#"//return/myMainList/mySubList[%d]",i ];
NSString *parsedNumbers = [node nodeStringForXPath:[xmlDataFetcher stringByAppendingString:#"/mySharedNumber"]];
NSString *parsedEdit = [node nodeStringForXPath:[xmlDataFetcher stringByAppendingString:#"/edited"]];
NSLog(#"Parsed Edited %#", [node nodeStringForXPath:[xmlDataFetcher stringByAppendingString:#"/edited"]]);
NSLog(#"Parsed sharedNumber %#", [node nodeStringForXPath:[xmlDataFetcher stringByAppendingString:#"/mySharedNumber"]]);
NSString *arrayEntry = [NSString stringWithFormat:#"%#%#", parsedNumbers, parsedEdit];;
[mySharedListArray addObject:arrayEntry];
}
NSLog(#"Array entry %#", mySharedListArray);
I have added a lot of NSLog in the answer, so that you could log it as you wish
I haven't done this most probably this is returning an array from the xpath query so Try this instead
[mySharedListArray addObjectsFromArray:[node nodesForXPath:#"//return/MyList" error:nil]];

How to search in NSArray?

I am having an array like fallowing,
NSArray*array = [NSArray arrayWithObjects:#"1.1 something", #"1.2 something else", #"1.3 out of left field", #"1.4 yet another!", nil];
Now,i am having the string like fallowing,
NSString*str = #"1.3";
Now i will send the str .Then it needs to find that str in array and it need to return the index of object where that text found.Means i need index 2 has to come as output.Can anyone share the code please.Thanks in advance.
Here is an example using blocks, notice the method: hasPrefix:
NSArray *array = [NSArray arrayWithObjects:#"1.1 problem1", #"1.2 problem2", #"1.3 problem3", #"1.4 problem4", nil];
NSString *str = #"1.3";
NSUInteger index = [array indexOfObjectPassingTest:
^(id obj, NSUInteger idx, BOOL *stop) {
return [obj hasPrefix:str];
}];
NSLog(#"index: %lu", index);
NSLog output:
index: 2
First a comment,
NSString *str = 1.3;
does not create an NSString object. You should instead have
NSString *str = #"1.3";
To search the NSArray, you will either have to change the string to the exact string in the array or search the NSString as well. For the former, simply do
float num = 1.3;
NSString *str = [NSString stringWithFormat:#"%.1f problem%d",num,(num*10)%10];
[array indexOfObject:str];
You can get fancier using NSPredicates as well.
Try
NSString *searchString = [str stringByAppendingFormat: #" problem%#", [str substringFromIndex: 2]];
NSUInteger index = [array indexOfObject: searchString];
Or (because you somehow like oneliners):
[array indexOfObject: [[array filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: #"SELF beginswith %#", str]] objectAtIndex: 0]];
The simplest way is to enumerate through values of array and check substrings:
NSArray *array = [NSArray arrayWithObjects: #"1.1 something", #"1.2 something else", #"1.3 out of left field", #"1.4 yet another!", nil];
NSString *str = #"1.33";
int i = -1;
int index = -1;
for (NSString *arrayString in array) {
i++;
if ([arrayString rangeOfString: str].location != NSNotFound) {
index = i;
break;
}
}
NSLog(#"Index: %d", index);
Not optimal but will work.

NSArray componentsSeperatedByString Sigabrt

I get a Sigabrt at the NSlog and i have no idea why - any suggestions?
NSString* contentList = [NSString stringWithContentsOfFile:currentFilePath encoding:NSUTF8StringEncoding error:nil];
NSArray* contentArray = [contentList componentsSeparatedByString:#"$$"];
NSLog(#"%#%#",contentList,[contentArray count]);
kunden = [contentArray objectAtIndex:0];
kundenView.text = kunden;
Following Joes suggestions, I now got:
NSString* contentList = [NSString stringWithContentsOfFile:currentFilePath encoding:NSUTF8StringEncoding error:nil];
NSArray* contentArray = [[contentList componentsSeparatedByString:#"$$"] retain];
if ([contentArray count] > 0) {
NSLog(#"%#%#",contentList,[contentArray count]);
kunden = [contentArray objectAtIndex:0];
kundenView.text = kunden;
}
Which gives me an EXC_BAD_ACCESS at the NSLog thing.
I get a Sigabrt at the NSlog
Your NSLog statement is trying to print an integer as if it was an object:
NSLog(#"%#%#",contentList,[contentArray count]);
^
Here!
Replace %# with %d.
You can read more on format specifiers in the String Programming Guide.
You are not checking to make sure you have at least 1 element in your array. Accessing [contentArray objectAtIndex:0] will be an issue if the contentArray is empty.