Got an error when try to print stringByReplacingOccurrencesOfString method - objective-c

When i try to print this string i got bad access error:
NSString *myPath = [myPath stringByReplacingOccurrencesOfString:#"/Users/Me/Library/iPhone/4.2/MyApp/Documents/Photos/pic1.png"
withString:#"/Users/John/Library/iPhone/5/MyApp/Documents/Photos/picture.png"];
NSLog(#"%#", myPath);
Why?
Thanks.

The error is because you are calling the method stringByReplacingOccurrencesOfString:withString on a variable (myPath) that has not been instantiated. You need to call that method on an instance of the NSString class that already contains the string you are replacing text in.

When you call a method you call it on the receiver. Therefore you are calling stringByReplacingOccurrencesOfString:withString: on myPath.
You are assigning the value of the method into
NSString *myPath
which makes me assume that the myPath in
[myPath ....
is not actually set to anything. (potentially pointing to garbage)
What you want is something like this
NSString *startString = #"hello";
// Receiver Message
// | |
// v v
NSString *replacedString = [startString stringByReplacingOccurrencesOfString:#"hello"
withString:#"bye bye"];
NSLog(#"Results in => %#", replacedString);
// Output
2011-12-11 20:50:01.964 Untitled 2[779:707] Results in => bye bye
In your above comment you tried NSString *myPath = [[NSString alloc] init]; this would create an empty string. An empty string does not contain any occurrences of #"/Users/Me/Library/iPhone/4.2/MyApp/Documents/Photos/pic1.png" therefore it can't replace them.

Related

Get a Objective-C method to return several NSStrings

I need to use a method that returns several strings, different ones, according to a value.
My code looks like:
- (void) returnStringsAccordingToSet:(NSString *)string1: (NSString *)string2: (NSInteger)setNo {
switch (setNo){
case 1:
if (generalStringSettings){
string1 = #"The first string";
string2 = #"The second string";
} else {
string1 = #"The first other string";
string2 = #"The second other string";
}
break;
case 2:
...
break;
case 3:
...
break;
}
}
I call that method with:
NSString *firstString = [[NSString alloc]init];
NSString *secondString = [[NSString alloc]init];
NSUInteger set = 1;
[self getStringsAccordingToSet: firstString: secondString: set];
I can't get it to work! All I get is empty strings. I've got a feeling that the call for the strings is somewhat wrong. Please help.
You can't mae it work because when you do
string1 = #"The first string";
you just override the local parameter and update its reference but nothing outside the callee is modified. So the value is changed just inside the scope of the function.
You should change the signature of the method to
- (NSArray*) returnStringsAccordingToSet:(NSString *)string1: (NSString *)string2: (NSInteger)setNo {
so that it returns a NSArray instead that nothing and then inside the function
case1:
return [NSArray arrayWithObjects:#"The first string",#"The second string",nil];
so you return the array and store it from the caller, then you can access the returned values.
NSArray *v = [returnStringAccordingTo: ..];
[v objectAtIndex:0]
Technically, since ObjectiveC is a superset of C, I guess it is possible to pass a pointer to a pointer to NSString by reference through (but this is discouraged in ObjC):
NSString *string = nil;
[self callMethod:&string];
-(void)callMethod:(NSString**)refToString {
*refToString = #"foobar";
You could do this by filling a NSArray, but just to show how C works I'll show the error that you made.
string1 and string2 are just pointers, so you can pass either mutable or immutable strings as arguments.But the original pointer never gets modified, for example:
NSString* string1=#"Hello"; // Let's suppose string1 is on the 0x8000 address
// And points to the 0x9000 address
NSString* string2=#"How are you?"; // string2: 0x1000 , pointing to 0x2000
[self returnStringsAccordingToSet: string1: string1 string2: string2];
Then when you call a method a copy is made for every pointer that you pass to the method:
- (void) returnStringsAccordingToSet:(NSString *)string1: (NSString *)string2: (NSInteger)setNo {
// string1 and string2 both point on the same address, but they are other pointers
// for example string1 is on 0x7000 and string2 on 0x7400, pointing to 0x9000
// and 0x2000
switch (setNo){
case 1:
if (generalStringSettings){
string1 = #"The first string"; // You just create another instance
string2 = #"The second string"; // of the string, but the original
// pointers aren't affected
} else {
string1 = #"The first other string";
string2 = #"The second other string";
}
break;
case 2:
...
break;
case 3:
...
break;
}
}
The solutions:
Pass a NSMutableString as argument and instead of assigning them, just modify the contents;
Pass a pointer to pointer;
Return a NSArray containing the new strings.
Update note: I personally don't use the method as a first thing to do. I use arrays if that's possible. Not sure if it's OK to use this with ARC. Some Apple methods use this approach to return error value, so it's good to be aware of it.
When method is called, those arguments you pass to function are copied (of course they are not getting the copy message, pointer is copied as far as you pass pointer), and those copies are used inside the function (or more technically initiated with the argument value). So if you change the copy (i.e. try to replace object on pointer, mutable objects are OK to modify) this will not reflect on the value. You may solve this using pointers (i.e. pass pointer to pointer).
So:
NSString* string = #"one string";
NSLog(string); // one string
// [self method:string]
- (void) method: (NSString*) string {
// Local copy created:
// NSString* string = copy of string (second pointer created, object not copied in memory)
string = #"other string";
NSLog(string); // other string
}
NSLog(string); // one string
You may do this like that:
- (void) method: (NSString**)str {
*str = #"Some string";
}
and then:
// string = "old vlalue"
NSString* string = #"old value";
// string = "Some string"
[self method:&string];

NSString Somehow turn in to an "__NSArrayI" object

i am receiving response from my server, it looks like this :
2012-09-12 16:29:11.690 WhatIsIt[1763:707] (
{
qid = ebb81a9c0c2125c9f12fee33c281dfe2ef5c1596;
"qid_data" = {
labels = Wristwatch;
};
} )
when i am parsing the "qid" value like this :
- (void)updateCompleteWithResults:(NSArray*)results{
NSLog(#"%#",results);
NSString *qid = [results valueForKey:#"qid"];
the NSString object is getting a Parentheses around the string (i dont know how)
looks like this :
2012-09-12 16:34:17.979 WhatIsIt[1785:707] (
2e1da5854f3b4f02cd967293cd1364e6d3e0b76a
)
so i tried to use :
NSString *string = #" spaces in front and at the end ";
NSString *trimmedString = [string stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
and the app crashes, any idea?
The problem is the root object of this structure is an array...
If you look at the valueForKey: method on NSArray you'll see that it will actually call valueForKey: on each of it's members and return the results in another array (this is what you are seeing).
What you should do instead is first get the object you are interested in and then work with it on it's own
NSDictionary *myObject = [whatIsIt objectAtIndex:0];
NSString *qId = [myObject objectForKey:#"qid"];

Why doesn't NSString getCharacters work in xcode?

-(void)myFunction {
unichar myBuffer[5];
NSRange range = {0, 3};
NSString *string = [NSString alloc];
string = #"123";
[string getCharacters:myBuffer :range];
}
Gets warning
! NSString may not respond
to '-getCharacters::'
then does a SIGABRT when I run it.
Why????? Or better yet how can I get it to work?
To use getCharacters:range:, write this line of code:
[string getCharacters:myBuffer range:range];
In Objective-C, method names are split up by arguments (a feature that derives from its Smalltalk heritage). So your original code was trying to send a message that's essentially named getCharacters: :, which isn't found. The corrected version sends the message getCharacters: range:.
The getCharacters:myBuffer construct says that the first argument to getCharacters:range: is myBuffer. Similarly, the range:range construct says the second argument is your NSRange named range.

Is it necessary to assign a string to a variable before comparing it to another?

I want to compare the value of an NSString to the string "Wrong". Here is my code:
NSString *wrongTxt = [[NSString alloc] initWithFormat:#"Wrong"];
if( [statusString isEqualToString:wrongTxt] ){
doSomething;
}
Do I really have to create an NSString for "Wrong"?
Also, can I compare the value of a UILabel's text to a string without assigning the label value to a string?
Do I really have to create an NSString for "Wrong"?
No, why not just do:
if([statusString isEqualToString:#"Wrong"]){
//doSomething;
}
Using #"" simply creates a string literal, which is a valid NSString.
Also, can I compare the value of a UILabel.text to a string without assigning the label value to a string?
Yes, you can do something like:
UILabel *label = ...;
if([someString isEqualToString:label.text]) {
// Do stuff here
}
if ([statusString isEqualToString:#"Wrong"]) {
// do something
}
Brian, also worth throwing in here - the others are of course correct that you don't need to declare a string variable. However, next time you want to declare a string you don't need to do the following:
NSString *myString = [[NSString alloc] initWithFormat:#"SomeText"];
Although the above does work, it provides a retained NSString variable which you will then need to explicitly release after you've finished using it.
Next time you want a string variable you can use the "#" symbol in a much more convenient way:
NSString *myString = #"SomeText";
This will be autoreleased when you've finished with it so you'll avoid memory leaks too...
Hope that helps!
You can also use the NSString class methods which will also create an autoreleased instance and have more options like string formatting:
NSString *myString = [NSString stringWithString:#"abc"];
NSString *myString = [NSString stringWithFormat:#"abc %d efg", 42];

Need formatting help for isEqualToString args

Code sample:
NSString *title = [[NSString alloc]initWithFormat: #"%#", [self.answers valueForKey:idVor]];
NSString *message = [[NSString alloc]initWithFormat: #"%#",nameVor];
NSLog(#"%#", title);
NSLog(#"%#", message);
if([title isEqualToString:message])
NSLog(#"equal");
The vars title and message never respond to the if statement even though they contain the same string.
I ran NSLogs for these to see what was contained in each string var.
I got the following output:
f[Session started at 2009-09-21 17:27:56 -0500.]
2009-09-21 17:28:00.256 pickerReview[2394:20b] (
Amedee
)
2009-09-21 17:28:00.257 pickerReview[2394:20b] Amedee
I guess it's not equal because the NSString title var has parentheses around it... Is there a way to format this so that it satisfies the expression in the if statement?
The issue appears to be that you're asking self.answers (an NSArray) for its valueForKey:#"whatever" — this doesn't return a string, but an array made up of the result of asking each object in the array for that key value. NSArray's description method (what gets printed when you NSLog it) is the contents of the array surrounded by parentheses. So you're comparing a string to an array containing a string.