Objective-c Substring Range Exception - iphone

I am creating an imap client. I want to parse body and header of incoming data but it crashes. I couldn't understand why it crashes and gives substring out of range error. How can I fix it?
I only want to check if the incoming string contains "FETCH" so I parse data, since string comes like
* FETCH or * 1 FETCH I thought checking isEqualToString range of (4,6) would be enough but that didn't work.
- (NSString*) readLine
{
NSMutableData* data = [[NSMutableData alloc] init];
unsigned char c;
for (;;) {
recv(socket_, &c, sizeof(c), 0);
if (c == '\n') {
NSString* s = [[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding];
NSString *str = [s substringWithRange:NSMakeRange(4, 6)];
if( [str isEqualToString:#"FETCH "]){
NSMutableArray *substrings = [NSMutableArray new];
NSScanner *scanner = [NSScanner scannerWithString:s];
[scanner scanUpToString:#"}" intoString:nil];
while(![scanner isAtEnd]) {
NSString *substring = nil;
[scanner scanString:#"}" intoString:nil];
if([scanner scanUpToString:#"*" intoString:&substring]) {
// If the space immediately followed the }, this will be skipped
[substrings addObject:substring];
}
[scanner scanUpToString:#"}" intoString:nil]; // Scan all characters before next }
}
NSString *email;
[emailList addObject:#"Select an Email"];
for(int i=0; i<substrings.count;i++){
email = [substrings objectAtIndex:i];
[emailList addObject:email]; // add emails in emailList
}
[substrings release];
}
if (nil != s) {
NSLog(#"%#",s);
}
[data release];
return [s autorelease];
}
else {
[data appendBytes: &c length: 1];
}
}
return nil;
}
output is:
* 1 FETCH (BODY[HEADER.FIELDS (FROM SUBJECT DATE)] {149}
2011-11-07 23:32:24.363 SwitchDeneme[327:bc03] Date: Mon, 07 Nov 2011 17:00:25 -0500 (EST)
2011-11-07 23:32:24.364 SwitchDeneme[327:bc03] From: "AOLWelcomeInfo" <AOLWelcomeInfo#message.aol.com>
2011-11-07 23:32:24.365 SwitchDeneme[327:bc03] Subject: Welcome to Your New Email Account!
2011-11-07 23:32:24.367 SwitchDeneme[327:bc03] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFString substringWithRange:]: Range or index out of bounds'
terminate called throwing an exceptionsharedlibrary apply-load-rules all

The problem is that your string is likely shorter than 7 characters, meaning it does not have an index of 6.
Try something more like this:
NSRange range = [someString rangeOfString:#"FETCH "];
if( range.location != NSNotFound ) {
//found it... so now do you processing...
}

You allocate and initialize an NSData object, then use that empty data object to initialize a string, so that string is empty.

Related

String not getting split giving unrecognized selector error

Trying to split the string in to array, but it is giving error "[__NSArrayI componentsSeparatedByString:]: unrecognized selector sent to instance 0x11741b20'". The string contains the value, that comes from first index of array then the string needs to be split and store in array.
This is array value.
mcommarr:(
":comment",
":comment",
":comment"
NSString *strr = [[NSString alloc]init];
strr = [self.mCommArr objectAtIndex:indexVal];
NSArray *arr2 = [str componentsSeparatedByString:#","];
Here is the complete method in which i am using this.
-(void)loadData:(int)indexVal;
{
indexVal=serialIndexVal;
serialIndexVal++;
NSLog(#"arrLike:%d", [self.mArrLike count]);
NSLog(#"arrPid:%d", [self.mArrPid count]);
status = [NSString stringWithFormat:#"get"];
[self.mButtonsStatusDict setObject:status forKey:#"status"];
[self.mButtonsPidDict setObject:[self.mArrPid objectAtIndex:indexVal] forKey:#"pid"];
[self.activityIndicator startAnimating];
#try
{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSString *status = [NSString stringWithFormat:#"get"];
[self.mButtonsStatusDict setObject:status forKey:#"status"];
[self.mButtonsPidDict setObject:[self.mArrPid objectAtIndex:indexVal] forKey:#"pid"];
self.mButtonsCommentsDict = [MyEventApi showComments:self.mButtonsPidDict];
self.mButtonsDict = [MyEventApi likeDislike:self.mButtonsUidDict post:self.mButtonsPidDict postStatus:self.mButtonsStatusDict];
dispatch_sync(dispatch_get_main_queue(), ^{
[self.activityIndicator stopAnimating];
NSLog(#"buttons data dict:%#", self.mButtonsDict);
if([self.mButtonsDict count] == 0)
{
NSLog(#"server problem no response");
[self.mArrLike addObject: #"0"];
[self.mArrDislike addObject: #"0"];
}else{
[self.mArrLike addObject: [self.mButtonsDict valueForKey:#"like"]];
[self.mArrDislike addObject: [self.mButtonsDict valueForKey:#"dislike"]];
}
if([self.mButtonsCommentsDict count] == 0)
{
NSLog(#"server problem no response");
[self.mCommArrTot addObject: #"0"];
}
else{
self.dictComm = [self.mButtonsCommentsDict valueForKey:#"comments"];
[self.mCommArr addObject:[self.dictComm valueForKey:#"comment"]];
NSLog(#"count:%d",[self.mCommArr count]);
// NSString *strTot = [NSString stringWithFormat:#"%d",tot];
// [self.mCommArrTot addObject:strTot];
NSLog(#"dictcomm:%#", self.dictComm );
NSLog(#"mcommarr:%#", [self.mCommArr objectAtIndex:indexVal]);
strr = [[NSString alloc]init];
strr = [self.mCommArr objectAtIndex:indexVal];
//NSString *strr = [[NSString stringWithFormat:#"%#", [self.mCommArr objectAtIndex:indexVal]];
// NSArray *arr1 = [self string:strr];
// NSArray *splitArray=[self.mCommArr[0] componentsSeparatedByString:#","];
//[strr componentsSeparatedByString:#","];
// NSLog(#"arrSep:%#", arr1);
//int count = [arr1 count];
//NSLog(#"arrcount:%d", count);
// NSString *strTot = [NSString stringWithFormat:#"%d",count];
// [self.mCommArrTot addObject:strTot];
//NSLog(#"mcommarrtot:%#", [self.mCommArrTot objectAtIndex:indexVal]);
}
// NSLog(#"arrLike:%#", [self.mArrLike objectAtIndex:indexVal]);
// NSLog(#"arrDisLike:%#", [self.mArrLike objectAtIndex:indexVal]);
[self.mPublicFriendTable reloadData];
});
});
}
#catch (NSException *exception) {
NSLog(#"main: Caught %#: %#", [exception name], [exception reason]);
}
#finally {
}
}
It get killed when try to split. Why so, i am not getting. If anyone has faced such situation please guide what is wrong her.
You can split the string into an NSArray like below...
NSString *yourString = #"comment,comment,comment";
NSArray *strArray = [yourString componentsSeparatedByString:#","];
NSLog(#"\n\n Array is ==>> %#",strArray);
"[__NSArrayI componentsSeparatedByString:]:
Your error says you tried to send the above method to NSArray, which doesn't has.
As you want to split the array at index 0. you should probably do as :
NSArray *splitArray=[yourArray[0] componentsSeparatedByString:#","];
Here yourArray is the array that you get from Server.
NSString *strr = [[NSString stringWithFormat:#"%#", [self.mCommArr objectAtIndex:indexVal]];
NSArray *arr2 = [strr componentsSeparatedByString:#","];
I think you are passing str right now, which can be an array (as your error points out).
Let me know the results.

application crashes when appendString for NSMutableString is used

I'm new to objective-c and I decided to start by working through Stanford's CS193s 2010F Session's lectures/assignments.
I was working on the second assignment, and I was stuck when I had to return a NSString that combines(concatenates) every strings inside NSMutableArray. (The MutableArray consists only NSString at its each indices)
My approach was to use a for loop to pass through the MutableArray's indicies(in the code below, the MutableArray is 'anExpression' with type 'id'). I declared a NSMutableString and added NSString at each indices of 'anExpression' array. Here is the code:
+ (NSString *)descriptionOfExpression:(id)anExpression{
NSMutableString *result = [NSMutableString string];
for (int i = 0;i<[anExpression count];i++){
[result appendString:[anExpression objectAtIndex:i]];
}
return result;
}
However, at
[result appendString:[anExpression objectAtIndex:i]];
xcode crashes with following error statements:
2012-07-17 01:44:51.014 Calculator[9470:f803] -[__NSCFNumber length]: unrecognized selector sent to instance 0x68732c0
2012-07-17 01:44:51.015 Calculator[9470:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0x68732c0'
*** First throw call stack:
(0x13ca022 0x155bcd6 0x13cbcbd 0x1330ed0 0x1330cb2 0x12d2d18 0x13460d7 0x1397a8d 0x3a50 0x27ed 0x13cbe99 0x1714e 0x170e6 0xbdade 0xbdfa7 0xbd266 0x3c3c0 0x3c5e6 0x22dc4 0x16634 0x12b4ef5 0x139e195 0x1302ff2 0x13018da 0x1300d84 0x1300c9b 0x12b37d8 0x12b388a 0x14626 0x1ed2 0x1e45 0x1)
terminate called throwing an exception
I looked through apple's developer's document, saw 'NSString stringWithFormat:' method, and decided to use this method instead:
+ (NSString *)descriptionOfExpression:(id)anExpression{
NSMutableString *result = [NSMutableString string];
for (int i = 0;i<[anExpression count];i++){
[result appendString:[NSString stringWithFormat:#"%#",[anExpression objectAtIndex:i]]];
}
return result;
}
and it works now.
now I'm confused why second code works but the first doesn't.
I thought appending string only fails(and crashes) when it's passed a nil...
Is there something I'm missing?
Thank you in advance :)
It looks like the contents of anExpression are instances of NSNumber instead of NSString. The error you are getting is a hint as to how appendString works; it's first step is obviously to ask the passed "string" how long it is (presumably so it can allocate enough memory). This is obviously not a method on NSNumber (hence the crash) and stringWithFormat is designed to do type-checking and be more flexible.
I suspect you could also use stringValue just as well:
[result appendString:[[anExpression objectAtIndex:i] stringValue]];
+ (NSString *)descriptionOfExpression:(id)anExpression{
NSMutableString *result = [NSMutableString string];
for (int i = 0;i<[anExpression count];i++) {
[result appendString:[[anExpression objectAtIndex:i] stringValue]];
}
return result;
}
Converting it into string would help you!!
Use this function:
+ (NSString *)descriptionOfExpression:(id)anExpression
{
NSMutableString *result = [[NSMutableString alloc] init];
for (int i = 0;i<[anExpression count];i++)
{
NSString *str = [NSString stringWithFormat:#"%#",[anExpression objectAtIndex:i]];
if(str)
{
[result appendString:str];
}
//OR
//[result appendFormat:[NSString stringWithFormat:#"%#",[anExpression objectAtIndex:i]]];
}
return result;
}

Add a character to a blank textfield

I'm new to xcode and am stuck on this one action.
I'm trying to add a "Negative" sign or "-" to a field when a button is clicked.
The following code works when someone enters a number into the field... it will add or remove a negative sign to it.
However, if the field is blank and you click on the button it throws an error.
Here's the code:
- (IBAction)fPosNeg:(id)sender {
NSMutableString *str = [userFahrenheit.text mutableCopy];
char iChar = [str characterAtIndex:0];
if (iChar == '-') {
userFahrenheit.text = [userFahrenheit.text substringFromIndex:1];
} else if (iChar != '-') {
[str insertString:#"-" atIndex:0];
userFahrenheit.text = str;
} else {
userFahrenheit.text = [NSString stringWithFormat:#"-"];
}
}
Here's the error:
Terminating app due to uncaught exception 'NSRangeException', reason:
'-[__NSCFString characterAtIndex:]: Range or index out of bounds'
You need to put a check before calling this -> [str characterAtIndex:0];
check will be
if(![str isEqualToString:#""]) // so that if string is blank, you cant access its character at index 0
NSMutableString *str = [NSMutableString stringWithString:#"-Test"];
char test = [str characterAtIndex:0];
NSMutableString *strFinal;
if (test == '-') {
strFinal = [NSMutableString stringWithString:[str substringFromIndex:1]];
}
else if (test != '-') {
[str insertString:#"-" atIndex:0];
strFinal=str;
}
else {
strFinal=[NSString stringWithFormat:#"-"];
}
NSLog(#"%#",strFinal);
You can also use this.
I think it's solve your problem.

Critical NSSstring Problem in Facebook friend Recovery(IPhone Development)

My Question is regarding special Character in NSString.
Actual name:- Yusuf Doğan
Retrieve name= Yusuf Do\u011fan
My Actual fb friend name is Yusuf Doğan (Check Special "g with ~ cap").
I take it as NSdata and then converter it in to nsstring.
NSString *stringResponse = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
But the nsstring shows it as
"Yusuf Do\u011fan"
Similar cause with the following.
Ricsi Zoványi as Ricsi Zov\u00e1nyi
Pero Perić as Pero Peri\u0107
Any Solution.
Thanks in advance.
You can try this:
NSString *source = [NSString stringWithString:_username];
[_username release];
NSMutableString *result = [[NSMutableString alloc] init];
NSScanner *scanner = [NSScanner scannerWithString:source];
[scanner setCharactersToBeSkipped:nil];
while (![scanner isAtEnd]) {
NSString *chunk;
// Scan up to the Unicode marker
[scanner scanUpToString:#"\\u" intoString:&chunk];
// Append the chunk read
[result appendString:chunk];
// Skip the Unicode marker
if ([scanner scanString:#"\\u" intoString:nil]) {
// Read the Unicode value (assume they are hexa and four)
unsigned int value;
NSRange range = NSMakeRange([scanner scanLocation], 4);
NSString *code = [source substringWithRange:range];
[[NSScanner scannerWithString:code] scanHexInt:&value];
unichar c = (unichar) value;
// Append the character
[result appendFormat:#"%C", c];
// Move the scanner past the Unicode value
[scanner scanString:code intoString:nil];
}
}
_username = [[NSString stringWithFormat:#"%#",result] retain];
[result release];
}
Instead of "NSUTF8StringEncoding" use "NSUTF16StringEncoding". I think this may solve your issue.

How to delete single characters in an UITextView

I have an UITextView which is for instance 380 characters in length:
NSLog(#"aTextView.text lenght %i", aTextView.text.length);
I now want to go through this text (backwards, char by char) and delete all characters which come before the last space (e.g. if the last words were "...this is an example", it want to reduce the string to "...this is an ":
for (int i = aTextView.text.length-1; i > 0; i--) {
NSString *checkedChar = [NSString stringWithFormat:#"%c", [aTextView.text characterAtIndex:i]];
NSLog(#"I currently check: %#", checkedChar);
if ([checkedChar isEqualToString:#" "]) {
// job done
i = 0; // this ends the loop
} else {
I need something like [aTextView.text removeCharacterAtIndex:i];
}
}
How do I achieve this? I couldn't find any methods in the docs and would be very grateful for suggestions.
EDIT:
NSString *myString = aTextView.text;
NSRange range = [myString rangeOfString:#" " options:NSBackwardsSearch];
NSString *oldText = [myString subStringToIndex:range.location];
NSString *newText = [myString subStringFromIndex:range.location];
NSLog(#"++++ OLD TEXT ++++: %#", oldText);
NSLog(#"++++ NEW TEXT ++++: %#", newText);
aTextView.text = oldText;
This crashes my app... I am calling this from - (BOOL)textView:(UITextView *)aTextView shouldChangeTextInRange:(NSRange)aRange replacementText:(NSString *)aText
I get the error message: * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSCFString subStringToIndex:]: unrecognized selector sent to instance 0x4e33850'
And xCode gives me the warning the subStringToIndex may not respond...
You don't need a loop to do this - take a look at NSString' rangeOfString:options: and substringToIndex: methods. For example :
NSRange range = [myString rangeOfString:#" " options:NSBackwardsSearch];
NSString *newString = [myString substringToIndex:range.location];
Hope that helps.
NB Don't forget to check that your string definitely contains a space ;)
This is very easy in iOS 5 or later:
// This is your delete button method.
-(IBAction)btnDelete:(id)sender
{
// txtView is UITextView
if([txtView.text length] > 0)
{
[txtView deleteBackward];
}
}