PDA

View Full Version : ERROR for attempting mutating immutable object




saleh.hi.62
Nov 25, 2011, 04:51 AM
what is this error? i am using mutable type but still it does not work!

ERROR IS :
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'mutate immutable object with deleteCharactersInRange:

Code is :
NSMutableString *line= [NSMutableString stringWithString:@"here is the string"];
[line deleteCharactersInRange: NSMakeRange(1,9 )];



jiminaus
Nov 25, 2011, 04:57 AM
You can't seriously expect us to believe that that's the code that is throwing that exception, can you?

saleh.hi.62
Nov 25, 2011, 05:04 AM
You can't seriously expect us to believe that that's the code that is throwing that exception, can you?

you try to copy and paste it in ur XCODE and see what will be the result.

jiminaus
Nov 25, 2011, 05:08 AM
you try to copy and paste it in ur XCODE and see what will be the result.

No, but there's got to be something between those two lines!


Look if you getting this exception then at some point you've assigned an NSString object into line.

If you want to confirm, log the actual class of the thing line is pointing to just before when you send it deleteCharactersInRange:.

chown33
Nov 25, 2011, 12:10 PM
you try to copy and paste it in ur XCODE and see what will be the result.

test1.m
#import <Foundation/Foundation.h>

int main( int argc, char *argv[] )
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

NSMutableString *line= [NSMutableString stringWithString:@"here is the string"];
NSLog( @"before: %@, len: %d", line, [line length] );
[line deleteCharactersInRange: NSMakeRange(1,9 )];
NSLog( @"after: %@, len: %d", line, [line length] );

[pool drain];
return 0;
}


Your posted code is hilited in red. It's exactly as you posted it.

Output:
2011-11-25 11:04:21.794 test1[8680] before: here is the string, len: 18
2011-11-25 11:04:21.795 test1[8680] after: he string, len: 9


Result: It works perfectly.

You should compile and run it yourself to confirm this result.

I hope this has demonstrated the value of writing tests. And then compiling and running them.

jiminaus
Nov 25, 2011, 03:38 PM
you try to copy and paste it in ur XCODE and see what will be the result.

I'd misread this sentence. I thought you were complaining about what would be results of copying and pasting your whole XCode project into a post.

If I copy and paste those two lines into main, I get:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '-[__NSCFString deleteCharactersInRange:]: Range or index out of bounds'

Which is perfectly understandable given that you've initialised your mutable string with length 0 and then tried to deleted characters from it.

And that's the kind of exception I knew that your code was going to produce. I could see straight away that it wasn't going to produce an exception about mutating an immutable object.

That's why I didn't waste my time at first actually running your code. And I'll thank you not to again waste mine, and others, time by not posting actual post relevant to your problem.


Ahhh, and now I've noticed you've edited your original post.
For the record, the original code posted was:

NSMutableString *line = [NSMutableString stringWithCapacity:0];
[line deleteCharactersInRange:NSMakeRange(1, 9)];

chown33
Nov 25, 2011, 04:01 PM
Ahhh, and now I've noticed you've edited your original post.
For the record, the original code posted was:

NSMutableString *line = [NSMutableString stringWithCapacity:0];
[line deleteCharactersInRange:NSMakeRange(1, 9)];


Wow. OP wins two Fail Whales. One for editing the original code to look less, well, failing. Two for editing it so it actually works, but still complaining: "you try to copy and paste it in ur XCODE and see what will be the result." (Look at the timestamps on the edit vs. the one on the complaint.)

chown33
Nov 25, 2011, 05:00 PM
I've been trying to produce the "mutate immutable object" error.

Given this code:

NSMutableString *line= [NSMutableString stringWithString:@"here is the string"];
[line deleteCharactersInRange: NSMakeRange(1,9 )];
here's one way to produce that error:

NSMutableString *line= [NSString stringWithString:@"here is the string"];
[line deleteCharactersInRange: NSMakeRange(1,9 )];
The blue hilite indicates the change, whose effects should be obvious to anyone who understands the fundamentals of mutable/immutable Foundation classes.

This change also fails:

NSMutableString *line= @"here is the string";
[line deleteCharactersInRange: NSMakeRange(1,9 )];
which should be as much of a surprise as water being wet.

saleh.hi.62
Nov 25, 2011, 09:37 PM
I ought to put the complete code here at first, i am sorry that posted this question incomplete!

here is the whole code:



NSRange range;
NSURL *url=[NSURL URLWithString:@"http://www.msn.com/robots.txt"];

NSString *content = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

NSArray *parsed = [content componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

NSMutableArray *robots=[[[NSMutableArray alloc] init] autorelease];

NSMutableString *line= [[[NSMutableString alloc] init] autorelease];


for(line in parsed){
range=[line rangeOfString:@"Disallow"];
if (range.location != NSNotFound) {
[line deleteCharactersInRange: NSMakeRange(1,9 )];
[robots addObject:line];

}
}

lee1210
Nov 25, 2011, 09:52 PM
http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/occ/instm/NSString/componentsSeparatedByCharactersInSet:

Does that say the list will be of mutable strings? Especially if you pass this to an immutable string?

You can easily just get a substring rather than modifying the immutable string in-place. I'd do that and store the new substring and be done with it.

-Lee

Edit: Also, robots needs to be an array, you alloc/init a mutable string and assign it there.

saleh.hi.62
Nov 25, 2011, 10:06 PM
http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/occ/instm/NSString/componentsSeparatedByCharactersInSet:

Does that say the list will be of mutable strings? Especially if you pass this to an immutable string?

You can easily just get a substring rather than modifying the immutable string in-place. I'd do that and store the new substring and be done with it.

-Lee

Edit: Also, robots needs to be an array, you alloc/init a mutable string and assign it there.
yes the error is what you mentioned. i revised it. but ! the what i am trying to do is that i want delete "Disallow" from all the elements in my array, any solution?

lee1210
Nov 25, 2011, 10:10 PM
yes the error is what you mentioned. i revised it. but ! the what i am trying to do is that i want delete "Disallow" from all the elements in my array, any solution?

I said I'd use a substring and that's still what I recommend:
http://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/occ/instm/NSString/substringFromIndex:

You'll get a new string, you store that, you move on.

-Lee

chown33
Nov 26, 2011, 09:41 AM
NSRange range;
NSURL *url=[NSURL URLWithString:@"http://www.msn.com/robots.txt"];

NSString *content = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];

NSArray *parsed = [content componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];

NSMutableArray *robots=[[[NSMutableArray alloc] init] autorelease];

NSMutableString *line= [[[NSMutableString alloc] init] autorelease];


for(line in parsed){
range=[line rangeOfString:@"Disallow"];
if (range.location != NSNotFound) {
[line deleteCharactersInRange: NSMakeRange(1,9 )];
[robots addObject:line];

}
}


...

yes the error is what you mentioned. i revised it. but ! the what i am trying to do is that i want delete "Disallow" from all the elements in my array, any solution?

The solution is to Follow the robot exclusion standard (http://en.wikipedia.org/wiki/Robots_exclusion_standard).

That means when the robots.txt file says "Disallow", you follow that exclusion. You don't delete the word "Disallow" and go on a malicious webcrawling spree.

If you're going to make a webcrawler, you should cooperate with the websites you're crawling. Don't be a bad web citizen. For example, read Wikipedia's robots.txt (http://en.wikipedia.org/robots.txt) file. Notice all the bad citizens who are disallowed.


At this point, I'm no longer going to give you any programming advice.

I recommend that everyone else be aware that you're asking how to make an ill-behaved and possibly malicious webcrawler. It's the only logical reason I can think of for removing Disallow from robots.txt files.

saleh.hi.62
Dec 1, 2011, 10:43 AM
The solution is to Follow the robot exclusion standard (http://en.wikipedia.org/wiki/Robots_exclusion_standard).

That means when the robots.txt file says "Disallow", you follow that exclusion. You don't delete the word "Disallow" and go on a malicious webcrawling spree.

If you're going to make a webcrawler, you should cooperate with the websites you're crawling. Don't be a bad web citizen. For example, read Wikipedia's robots.txt (http://en.wikipedia.org/robots.txt) file. Notice all the bad citizens who are disallowed.


At this point, I'm no longer going to give you any programming advice.

I recommend that everyone else be aware that you're asking how to make an ill-behaved and possibly malicious webcrawler. It's the only logical reason I can think of for removing Disallow from robots.txt files.

yes, i am trying to write a web crawler, but what i am trying to is to have the Disallow links in any array to avoid crawling them, so i want to remove the word disallow then store it in array. not doing something else! ;)