How to write this method in Objective-C? - iphone

I just started Objective-C recently, and this has once again gotten me to the point of asking SO for help. I need to rewrite this method so that I can call it using [self URLEncodedString];
This is what the method currently looks like -
- (NSString *)URLEncodedString {
NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR("!*'();:#&=+$,/?%#[]"), kCFStringEncodingUTF8);
[result autorelease];
return result;
}
But I can't call it like [self URLEncodedString]; How can I rewrite it so that it would work for me to be able to call it using [self URLEncodedString];?
P.S. Calling it via [strValue URLEncodedString]; doesn't work, hence the reason I'm making this post.
Thanks for any help!

I think what you're asking for is to create an NSString category which will encode your string.
You need to create a new set of files, name them something that makes sense (NSString+URLEncoding).
In the .h file, you'll need something like this:
#interface NSString (URLEncoding)
- (NSString*)URLEncodedString;
#end
Then in your .m file:
#implementation NSString (URLEncoding)
- (NSString *)URLEncodedString {
NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR("!*'();:#&=+$,/?%#[]"), kCFStringEncodingUTF8);
[result autorelease];
return result;
}
#end
When you want to use this method, you'll need to make sure you import "NSString+URLEncoding.h".
You can then do something like this:
NSString * firstString = #"Some string to be encoded %&^(&(!#£$%^&*";
NSString * encodedString = [firstString URLEncodedString];
Hope that helps.

Why not just use the NSString instance method stringByAddingPercentEscapesUsingEncoding?

Related

ios - How to call a method from another class dynamically in a string?

I'm new to iPhone development,I want to call a method from another class in String
In LoginSuccess.m
- (void)Post:(NSString *)url AndSecondStr:(NSString *)postData AndThirdStr:(NSString *)contentType
In Register.m
LoginSuccess *loginViewInstance = [[LoginSuccess alloc]initWithNibName:#"LoginSuccess" bundle:nil];
[loginViewInstance Post:TxtEmailId AndSecondStr:TxtUserName AndThirdStr:serializeObject];
above one is executed,but I want to call that method in String like
NSString *result = [loginViewInstance Post:TxtEmailId AndSecondStr:TxtUserName AndThirdStr:serializeObject];
Any ideas? Thanks in advance.
replace
- (void)Post:(NSString *)url AndSecondStr:(NSString *)postData AndThirdStr:(NSString *)contentType
with
- (NSString *)Post:(NSString *)url AndSecondStr:(NSString *)postData AndThirdStr:(NSString *)contentType
{
NSString *str;
str = someValue;
return str;
}
your return type data is (void). please first replace it with NSString like:
(NSString *)Post:(NSString *)url AndSecondStr:(NSString *)postData AndThirdStr:(NSString *)contentType
{
//do something
}
then to call a method from another class you can do it
like first add this code in Register.m.
#import "LoginSuccess.h"
and then call it like:
LoginSuccess *Call_String = (LoginSuccess *)[LoginSuccess sharedApplication];
NSString *result = [Call_String Post:TxtEmailId AndSecondStr:TxtUserName AndThirdStr:serializeObject];
hope your problem will be solved

Add text/data along with special characters as a parameter to api(url) in iphone

I am new to Obj-c. I am adding parameter like text (the text may have special characters also)to url. But the url is showing nil, it's not taking value from string.
For example:
NSString*strUrl=[NSString stringWithFormat:#"hi how#!#$%^^&*()_=+ r u <>,./ where r u"];
NSString *strMainUrl=[NSString stringWithFormat:#"http://google.com/API/index.php action=listIt&data=%#",strUrl];
NSString *encodeStr = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url=[NSURL URLWithString:encodeStr];
NSLog(#" url is =%#",url);
But the url is showing nil value. It's not taking "encodeStr" value. How can I solve this problem.Please help me.
I tried with..
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:str] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];
and also
strEncode=[strEncode stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
Modified example from here:
#import <Foundation/Foundation.h>
// In case you're unfamiliar, this is a category, which allows us to add methods
// to an existing class, even if we didn't create it. It's a nice alternative
// to subclassing.
//
// In this case, we're extending NSString
#interface NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding;
#end
#implementation NSString (URLEncoding)
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)#"!*'\"();:#&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool
{
NSString *raw = #"hi how#!#$%^^&*()_=+ r u <>,./ where r u";
// note also, that your string omits the '?' in the URL
NSString *url = [NSString stringWithFormat:#"http://google.com/API/index.php?action=listIt&data=%#",
[raw urlEncodeUsingEncoding:NSUTF8StringEncoding]];
NSURL *finalUrl = [NSURL URLWithString:url];
NSLog(#"%#", finalUrl);
}
}
Output:
http://google.com/API/index.php?action=listIt&data=hi%20how%40%21%23%24%25%5E%5E%26%2A%28%29_%3D%2B%20%20%20r%20u%20%3C%3E%2C.%2F%20where%20r%20u

clean way to add query string to NSString?

So I have a NSString with a url like this:
NSString stringWithFormat:#"/reading.php?title=blah&description="blah"&image_url=blah... "
what is the best way to append query string to this string? is there a dictionary kind of way to do this?
What you want to do is this.
[NSString stringWithFormat:#"/reading.php?title=blah&description=%#&image_url=blah... ",blah];
Basically %# in the context meaning that you'll pass use a dynamic value which will be a string.
How about a category?
This is not great but for a first pass should give you something to get started
#interface NSDictionary (ps_additions)
- (NSString *)ps_URLParamsValue;
#end
#implementation NSDictionary (ps_additions)
- (NSString *)ps_URLParamsValue;
{
NSMutableString *params = [NSMutableString string];
[self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
[params appendFormat:#"%#=%#&", key, obj];
}];
return [params copy];
}
#end
This would end up with something like:
NSDictionary *params = [NSDictionary dictionaryWithObjectsAndKeys:#"42", #"special_number", #"value", #"another", nil];
NSString *myString = [NSString stringWithFormat:#"/reading.php?%#", [params URLParamsValue]];
NSLog(#"%#", myString);
#=> 2012-03-20 23:54:55.855 Untitled[39469:707] /reading.php?another=value&special_number=42&
You can use something like:
NSString *parameter1 = #"blah";
NSString *parameter2 = #"anotherblah";
NSString *fullURL = [NSString stringWithFormat:#"/reading.php?title=%#&image_url=%#", parameter1, parameter2];
You can add as many parameters as you want. Use "%#" where you will be dynamically adding the text.
Good luck :)
Copy pasting from Paul.s - which is the correct answer, imo - and fixing a (most likely inconsequential) problem of a dangling ampersand...
#interface NSDictionary (ps_additions)
- (NSString *)ps_URLParamsValue;
#end
#implementation NSDictionary (ps_additions)
- (NSString *)ps_URLParamsValue;
{
if (!self.count) return #"";
NSMutableString *params = [NSMutableString string];
[self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
[params appendFormat:#"%#=%#&", key, obj];
}];
// return everything except that last ampersand
return [[params copy] substringToIndex:[params length]-1];
}
#end

Why does implicit initialization of a variable not work consistently on iPhone?

So here is my scenario -- In the header file of a class I do:
#interface MyClass : NSObject
{
NSString *string1;
NSString *string2;
}
- (void) methodOne: (NSString *) passedString;
- (void) methodTwo: (NSString *) passedString;
#end
In the implementation file I do this:
#import MyClass.h
#implementation MyClass
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
string1 = passedString;
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
string2 = passedString;
}
What I am finding is that there is some kind of inconsistency when doing this versus [NSString alloc] initWithString:].
As you can see string1 and string2 are treated exactly the same, but what is happening is that string1 is getting set, but string2 is remaining empty. I get a bad access when I reference it later.
I thought maybe I was passing an empty string to methodTwo: so I added that NSLog which proves that it is not empty, but has the expected string.
Since I have noticed this inconsistency before I decided to change to this:
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
string1 = passedString;
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
string2 = [[NSString alloc] initWithString: passedString];
}
Now both strings are working as expected. My question is why is there this inconsistency?
This is not the only time this has happened to me. It has happened with all kinds of objects. The only thing that seems to work every time is alloc init. Methods like stringWithString: work most of the time, but not always.
It's because in the first example, you don't retain or copy the strings. string2 is getting deallocated at some point before you use it. It's actually pure luck that string1 is OK. You should change your code to be something like this:
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
NSString* oldString = string1;
string1 = [passedString copy];
[oldString release];
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
NSString* oldString = string2;
string2 = [passedString copy];
[oldString release];
}
and release in dealloc
-(void) dealloc
{
[string1 release];
[string2 release];
// other stuff
[super dealloc];
}
I strongly recommedn you create properties for string1 and string2 to handle all that reference counting stuff:
#interface MyClass : NSObject
{
NSString *string1;
NSString *string2;
}
- (void) methodOne: (NSString *) passedString;
- (void) methodTwo: (NSString *) passedString;
#property (copy) NSString* string1;
#property (copy) NSString* string2;
#end
#imlementation MyClasss
#synthesize string1, string2;
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
[self setString1: passedString];
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
[self setString2: passedString];
}
// dealloc as before
#end
You are making memory management errors. You have to retain or copy the strings when you assign them to your ivars (and release them later).
It is possible that you can still access an object even though it has been deallocated when the memory it occupied has not been overwritten yet. But you cannot rely on it.
If the passed strings are autoreleased there is no retain when they are assigned. Constant strings (#str") essentially are never released, created strings such as by stringWithFormat need to be retained.
Please show the callers.
Using #properties with retain will eliminate many retain issues. Or consider using ARC, that eliminates the need for retain/release/autorelease.
As others have stated in this thread you have some memory management issues here, perhaps you aren't quite understanding the way that NSObjects get allocated and retained, you should read up on Objective-C memory management. In the mean time there are two approaches you could take to solve your above issue.
You could have your NSString member variables (string1 & string2) kept as properties of your class, aside from some other functionality declaring these as properties would give them setter and getter accessors, that you would call instead of method1 and method2. So this would change your code to look like the following in your header file
#interface MyClass : NSObject
{
NSString *string1;
NSString *string2;
}
#property( nonatomic, retain)NSString* string1;
#property( nonatomic, retain)NSString* string1;
Then remember to add the following to your source file (typically at the top of the file after the #implementation MyClass line)
#implementation MyClass
#synthesize string1;
#synthesize string2;
Then in the class where you were calling method1 and method2 from you can change the code to look like
//Lets assume somewhere you've called an init Method for your MyClass Object, something like
MyClass* myClassObject = [[MyClass alloc] init];
//you can then call the setters to set the string like so
[myClassObject setString1:#"some string"]; //or myClassObject.string1 = #"some string";
[myClassObject setString2:#"some string"]; //or myClassObject.string2 = #some other string";
//Calling these member variables either of the above ways is valid, I prefer the former as it's a bit easier on the eye for me
//and to get the values back out of the strings you could call
NSString* output = [myClassObject string1];
//or
NSString* output2 = myClassObject.string2;
Now you may for some reason not want to use an #property for the NSString member variables, so you could modify your original source (.m) file to look like
#implementation MyClass
- (void) methodOne: (NSString *) passedString
{
NSLog(#"%#", passedString);
if( string1 != nil )
{
[string1 release];
}
string1 = [[NSString alloc] initWithString:passedString];
}
- (void) methodTwo: (NSString *) passedString
{
NSLog(#"%#", passedString);
if( string2 != nil )
{
[string2 release];
}
string2 = [[NSString alloc] initWithString:passedString];
}
That should solve the issue of why your strings aren't valid, as you wont be overwriting the memory and trying to read back garbage this way. You will have to remember to release these NSStrings in your dealloc if they are not nil, otherwise you'll get a memory leak there too.
Hope this helps.

Method '-cleanTitle.' not found (return type defaults to 'id')

I'm trying to implement an rss feed into my app and I have created a method to clean the title up.
- (NSString *)cleanTitle:(NSString *)Title {
return [Title stringByReplacingOccurrencesOfString:#"twitterfeed: " withString:#""];
}
The warning occurs on the articleTitle line below:
- (void)parseAtom:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
NSString *blogTitle = [rootElement valueForChild:#"title"];
NSArray *items = [rootElement elementsForName:#"entry"];
for (GDataXMLElement *item in items) {
NSString *articleTitle = [self cleanTitle: [item valueForChild:#"title"]];
Do you know how to get rid of this warning?
Thanks.
Make sure - (NSString *)cleanTitle:(NSString *)Title is also declared in your header file.
The method's signature must be known before it is used if the two methods are not in the same category or class. If it's the same class but -cleanTitle: is in a (Private) category or some such, be sure to declare that category prior to your class' implementation (in your .m file) :
#interface MyClass (Private)
- (NSString *)cleanTitle: (NSString *)title;
#end