Getting an error when using replaceOccuranceOfString function - iphone

[str replaceOccurrencesOfString: withString: options: range:
[str replaceOccurrencesOfString:#"'" withString:#"!~" options:0 range:NSMakeRange(0,str.length)]
I am using this function to replace ' symbol in my NSMutableString with !~ symbol so that I can store that string into database. Its working fine when I stored it into database, but at the time of retrieving and convert it back using same function it showing me error like.
Error
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with replaceOccurrencesOfString:withString:options:range:'
Here, str is of NSMutableString type. I checked for its type [str class] its converts to NSCFString don't know why its changing? I also try to convert it to NSMutableString, but its not converting. I am trying for it for so many times in some other ways, but its working fine with all other places, only in my one view controller, it showing me this.
Any guesses where's I am doing wrong?

You don't show how you are converting the immutable from the data base to a mutable string. Just doing NSMutableString *mstr = str; isn't enough, you'd need to use NSMutableString *mstr = [NSMutableString stringWithString:str];.
Because the returned string is immutable you might want to consider using [NSString stringByReplacingOccurrencesOfString:withString:] instead of working with mutable strings.

Related

(Objective C) Obtain CFstringRef from NSMutableArray

I have an NSMutableArray that was downloaded via FTP. The elements in the array are CFFTPStream resource constants that are of type CFStringRef.
I would like to create a String from the "kCFFTPResourceName" constant. However being new to Objective C and iphone development I am struggling.
Everything that I have done has resulted in ARC throwing a fit or errors like:
2013-01-03 15:31:44.874 Street Light Reporter[1382:11603] -[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x6e1e930
2013-01-03 15:31:44.875 Street Light Reporter[1382:11603] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x6e1e930'
My most recent attempt is:
CFStringRef *c = [ar objectAtIndex:4];
which doesnt work for the following two reasons:
Incompatible pointer types initializing 'CFStringRef *' (aka 'const struct __CFString **') with an expression of type 'id'
AND
Implicit conversion of an Objective-C pointer to 'CFStringRef *' (aka 'const struct __CFString **') is disallowed with ARC
I have tried all sorts of typecasting and messing around with (__bridge) and whatnot and I have had no luck.
Can anybody help me out here? Any help will be appreciated.
CFStringRef is a pointer already, you don't need the star. Also, you can cast CFStringRef to NSString and it will work fine and will be easier to work with. This is called toll free bridging. If you still need the CFStringRef:
ARC:
CFStringRef c = (__bridge CFStringRef)([ar objectAtIndex:4]);
Non arc
CFStringRef c = (CFStringRef)([ar objectAtIndex:4]);
You have two errors here: the first and the most severe one is that your ar object is a NSDictionary not a NSArray. That's why performing
CFStringRef *c = [ar objectAtIndex:4];
you are getting a NSInvalidArgumentException. objectAtIndex: is a method of NSArray that you are sending to a NSdictionary instance.
The second error is the cast. As Fernando already pointed out, you need to cast it using the __bridge keyword like follows.
CFStringRef c = (__bridge CFStringRef)([ar objectAtIndex:4]);
so that ARC will know that you are now treating that object as a C pointer.
Note also that CFStringRef is defined as
typedef const struct __CFString * CFStringRef;
so it's already a pointer and you have to get rid of the *.
It seems that you get an CFDictionary back and not an array.
The constants you linked to are keys for the dictionary, with which you can access the values.

CFURLCreateStringByAddingPercentEscapes returning NULL

I am having issues with a category method used to percent-escape illegal symbols.
This is the code that i am using for the task:
#implementation NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
NSString *s = (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)self, NULL, (CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",CFStringConvertNSStringEncodingToEncoding(encoding));
NSLog(#"S: %#, Self: %#", s, self);
return [s autorelease];
}
#end
When ever i run this method on a string without any of the symbols found in the above matching-string, the method runs fine and the same string is returned back to me.
For instance if i have a string like #"test" it will output:
S: test, Self: test
But if i instead use a string like #"test&symbols" it will output:
S: null, Self: test&symbols
Hence something seems to be wrong with the use of CFURLCreateStringByAddingPercentEscapes.
Now i want to escape symbols such as & because they can occur in strings used as values in a query string, which would cause the query string to be misinterpreted.
Any idea's about what may be the issue here?
Thank you in advance! / Magnus
After finding out my big mistake.
I was told to answer the question to my self.
What i did wrong that i didn't pass NSStringEncoding value to the method, like NSUTF8StringEncoding but instead of that I was passing a CF value such as kCFStringEncodingUTF8.
The value is passed thru a converter to make it CF value which caused an error and it was already had the correct type.
Sorry for any inconvenience.
-Magnus

is NSString value cannot be changed once it is provided a value?

Hi I got an information that NSString value is immutable and cannot be changed once it is provided a value.
But I have created and tested the following code:
NSString *str=[[NSString alloc] initWithString:#"Hello"];
NSLog(#"\n\nstr = %#",str);
str=#"asdasd";
NSLog(#"\n\n new str = %#",str);
and this gives "Hello" as first str value and "asdasd" as second str value. If it is so what is the relevance of calling NSString immutable?Thanks in advance.
What you're doing on the third line is just creating a new string and pointing it with the str variable. You didn't change the original string, but rather made the variable point to a new one.
NSString is immutable. You cannot mutate it. Your confusion arises from the fact that your variable (pointer) is not const.
All you're doing is reassigning the pointer to a different immutable string.
If you were to attempt to append a string to either, then an error would ensue. This, specifically, is "…the relevance of calling NSString immutable". You should interpret this as the string instance may not be mutated, even though the variable you have declared may be assigned another NSString instance because it is not const.
You can make both the pointer const and the string immutable like so:
NSString * const aStr = #"aStr";
You're confusing an immutable object and a constant pointer (plus you're leaking memory). Here you don't really change the NSString instance (that is, the object itself), but just a pointer to it. The point is that you can assign different instances of an NSString to the same variable, it won't change the internal contents of the object, nor would it make it respond to NSMutableString's mutation messages such as appendString etc.
Use this will sol your problem...
NSString *str=[NSString stringWithFormat:#"Hello"];
NSLog(#"\n\nstr = %#",str);
str = nil;
str=#"asdasd";
NSLog(#"\n\n new str = %#",str);
This some basic that you should know..
NSString *s1 = #"string1";
NSString *s2 = [[NSString alloc] initWithString:#"string2"];
NSString *s3 = [NSString stringWithFormat:#"string3"];
s1 in this case is a pointer to a constant string. s2 and s3 both point to new strings that you've created, but s2 has been retained for you, and s3 has been autoreleased. If you just need a temporary object, the autoreleased object s3 or the constant object s1 are good choices. If you need to keep the string around, you should use s2 (actually now that I think about it s1 will work in this case too - it's not really idiomatic, though).
You can make s1 or s3 equivalent to s2 by sending them a retain message. You could also turn s2 into an equivalent object by sending it an autorelease message.

XCODE incompatible pointer type error

I am getting a casting error. My app is reading a text file from a webpage using 'stringWithContentsOfURL' method. I want to parse the individual lines into separate components. This is a snippet of the code.
int parameterFive_1 = 0;
parameterFive_1_range = NSMakeRange(0,10)
lines = [response componentsSeparatedByString:#"\r"];
parameterFive_1 = CFStringGetIntValue([[lines objectAtIndex:i] substringWithRange:parameterFive_1_range]);
I am getting the following error message:
" Implicit conversion of an Objective-C pointer to 'CFStringRef' (aka 'const struct __CFString *') is disallowed with ARC"
I thought it might be the compiler option but changing it to the default is not making a difference. Can anyone provide any insight?
Just cast the NSString* to CFStringRef to satisfy ARC:
parameterFive_1 = CFStringGetIntValue((__bridge CFStringRef)[[lines objectAtIndex:i] substringWithRange:parameterFive_1_range]);
The __bridge keyword here lets ARC know that it doesn't need to transfer ownership of the string.

Convert or Print CGPDFStringRef string

How to convert a CGPDFStringRef to unicode char? I have used CGPDFStringCopyTextString to get the string and then [string characterAtIndex:i] to cast to unichar, is this the right way? or is there any way to get the bytes of the string and convert to unicode directly?
Need some guidance here.
NSString is capable of handling of unicode characters itself, you just need to convert the CGPDFString to NSString and further you can use it as follows:
NSString *tempStr = (NSString *)CGPDFStringCopyTextString(objectString);
although UPT's answer is correct, it will produce a memory leak
from the documentation:
CGPDFStringCopyTextString
"...You are responsible for releasing this object."
the correct way to do this would be:
CFStringRef _res = CGPDFStringCopyTextString(pdfString);
NSString *result = [NSString stringWithString:(__bridge NSString *)_res];
CFRelease(_res);
It's not a bad idea, even if you can access the CGPDFString directly using CGPDFStringGetBytePtr. You will also need CGPDFStringGetLength to get the string length, as it may not be null-terminated.
See the documentation for more info