I'm diving into iOS development and I have a custom URL scheme for my iPhone app that looks like myApp://?q=200. I have the following code to get the query parameter...
NSString *urlString = [url absoluteString];
NSString *query = [urlString stringByReplacingOccurrencesOfString:#"myApp://?q=" withString:#""];
...but I'd like to make it a bit more future-proof in the event that I add more parameters. How can I extract the "q" parameter in a safer way?
Thanks in advance for your wisdom!
You can split the query returned from the URL by & and = and put them in a dictionary.
NSURL *url = [NSURL URLWithString:#"myApp://?q=200"];
NSArray *query = [[url query] componentsSeparatedByString:#"&"];
NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithCapacity:[query count]];
for(NSString *parameter in query)
{
NSArray *kv = [parameter componentsSeparatedByString:#"="];
[parameters setObject:[kv count] > 1 ? [[kv objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSISOLatin1StringEncoding] : [NSNull null]
forKey:[[kv objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSISOLatin1StringEncoding]];
}
NSLog(#"Parameters: %#", parameters);
NSLog(#"q = %#", [parameters objectForKey:#"q"]);
In this example if there is no value for the parameter I just set it to NSNull. This means you would either need to check for NSNull or change the logic to skip keys with values or set them to an empty string.
This from the top of my head could work but doesnt yet include error checking the input
-(NSDictionary*) parameterDictionaryFromString: (NSURL*) url {
//input can be something like: "myApp://?q=one&q2=two&q3=three"
NSString *requestString = [url query];
//now we have q=one&q2=two&q3=three
NSArray *requests = [requestString componentsSeparatedByString: #"&"];
NSMutableDictionary *resultDictionary = [NSMutableDictionary dictionary];
for (NSString *singleParameter in requests) {
NSArray *keyValuePair = [singleParameter componentsSeparatedByString: #"="];
[resultDictionary setObject: [keyValuePair objectAtIndex: 1] forKey: [keyValuePair objectAtIndex: 0]];
}
NSURL *u = [NSURL URLWithString: #"myApp://something?q=1&check=yes"];
NSLog(#"paramStr = %#", [u parameterString]);
return [resultDictionary copy];
}
Break the Query String by Distinct Separator,
Assure Valued Content provided at index:1 (The right-hand side of the query string break)
In valued content then use downstream, or set to upstream variable.
//Your Example:
//#"myApp://?q=200"
//Break:
NSArray *queryParts = [urlString componentsSeparatedByString:#"?q="];
//Assure Content:
if ([[array objectAtIndex:1] length]>0) {
//Setter:
NSString *queryString = [array objectAtIndex:1];
//... Use away...
}
The key is to leverage the NSArray class over StringReplace.
As the google doc is not available anymore, I'm lost with those concepts.
What is a node, and what is an element (that inherits the node) ?
How can I switch from nodes to elements. I mean, for example, if I write :
NSError* error;
NSData* xmlData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"ForTesting" ofType:#"xml"]];
error = nil;
GDataXMLDocument* XMLDoc = [[[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error] autorelease];
if (XMLDoc == nil) {
NSLog(#"%#", error.description);
return;
}
GDataXMLNode* xmlElement = [[XMLDoc nodesForXPath:#"//root/fileVersion" error:nil] objectAtIndex:0];
NSString* fileVersion = xmlElement.stringValue;
GDataXMLNode* xmlList = [[XMLDoc nodesForXPath:#"//root/list" error:nil] objectAtIndex:0]; // single item
After that code, how can I write something like that to switch to GDataXMLElement instead of continuing with GDataXMLNode, that would requires me to continue using XPath (I don't want to use it past that point) :
// code don't work : elementsForName is not defined for GDataXMLNode
for (GDataXMLElement* xmlObject in [xmlList elementsForName:#"object"]) {
MyClass* obj = [[[MyClass alloc] initWithXMLElement:xmlObject] autorelease];
}
GDataXMLNode is obviously the classes you use for XML parser- GDataXMLNode.h/.m
In the code you have given returns an array. You can use.
NSArray *myArray = [XMLDoc nodesForXPath:#"//root/fileVersion" error:nil];
You can iterate myArray like this.
for (GDataXMLElement *nodeXmlElt in myArray)
{
//some code
}
Each of my nodeXmlElt will be like given below.
<fileVersion>
<title>San Francisco CBS News</title>
<link>http://news.google.com/news/</link>
<fileVersion>
//getting title
NSArray *elementArray = [nodeXmlElt elementsForName:#"title"];
GDataXMLElement *gdataElement = (GDataXMLElement *)[elementArray objectAtIndex:0];
NSString *title = gdataElement.stringValue; //returns 'San Francisco CBS News'
-<stat>
<visitor>4</visitor>
<uniqueVisitor>2</uniqueVisitor>
<order>41</order>
<revenue>20658</revenue>
<conversionRate>48</conversionRate>
<newProduct>25</newProduct>
<outOfStockProduct>11</outOfStockProduct>
</stat>
From this xml i want to get the element name "visitor" & "uniqueVisitor" and their corresponding values using GDataXML parser.
Till now i have done these.
xmlFileLocation = [NSURL URLWithString:#"someurl....abc.php"];
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfURL:xmlFileLocation];
xmlDocument = [[GDataXMLDocument alloc]initWithData:xmlData options:0 error:&error];
if (nil == xmlDocument) {
NSLog(#"could not load Branch.xml file");
}
else {
NSLog(#"Loading desire xml url for dashboard");
[self GDataXmlParser];
}
Using a tutorial i have done this till now. But now i want all of these element name and their corresponding values
-(void)GDataXmlParser{
NSArray *getData = [[xmlDocument rootElement]elementsForName:#"stat"];
records = [[NSMutableArray alloc]init];
tempArray = [[NSMutableArray alloc]init];
for(GDataXMLElement *e in getData){
// What i have to do here????
}
}
look at the answer
NSLog(#"%#", xmlDocument.rootElement);
records = [[NSMutableArray alloc] init];
NSLog(#"Enering in the xml file");
NSString *Visitor = [[[xmlDocument.rootElement elementsForName:#"visitor"] objectAtIndex:0] stringValue];
NSLog(#"Visitor : %#",Visitor);
NSString *UVisitor = [[[xmlDocument.rootElement elementsForName:#"uniqueVisitor"] objectAtIndex:0] stringValue];
NSLog(#"Unique Visitor : %#",UVisitor);
for more see the link I am not able to parse xml data using GDataXML
Follow this link for tutorial :http://iphonebyradix.blogspot.com/2011/03/using-gdata-to-parse-xml-file.html
-(void) GDataXmlParser
{
xmlDocument = [[GDataXMLDocument alloc]initWithData:xmlData
options:0
error:nil];
NSArray *temp = [xmlDocument.rootElement elementsForName:#"stat"];
NSMutableArray *records = [[NSMutableArray alloc]init];
for(GDataXMLElement *e in temp)
{
[records addObject:e];
NSString *Visitor = [[[e elementsForName:#"visitor"] objectAtIndex:0] stringValue];
NSLog(#"Visitor : %#",Visitor);
NSString *UVisitor = [[[e elementsForName:#"uniqueVisitor"] objectAtIndex:0] stringValue];
NSLog(#"Unique Visitor : %#",UVisitor);
}
}
Hope it helps you. Happy iCoding.
The iPhone UIImagePickerControllerReferenceURL returns an URL as:
assets-library://asset/asset.PNG?id=1000000001&ext=PNG
What's the best (preferably simple) way to retrive 1000000001 and PNG as NSStrings from the above URL example?
Well, you can easily turn it into an NSURL by using +[NSURL URLWithString:]. From there you could grab the -query string and parse it out, something like this:
NSString *query = ...;
NSArray *queryPairs = [query componentsSeparatedByString:#"&"];
NSMutableDictionary *pairs = [NSMutableDictionary dictionary];
for (NSString *queryPair in queryPairs) {
NSArray *bits = [queryPair componentsSeparatedByString:#"="];
if ([bits count] != 2) { continue; }
NSString *key = [[bits objectAtIndex:0] stringByRemovingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *value = [[bits objectAtIndex:1] stringByRemovingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[pairs setObject:value forKey:key];
}
NSLog(#"%#", pairs);
Warning, typed in a browser, so some of my spellings may be wrong.
For IOS >= 4.0 you can use native regular expressions with NSRegularExpression class. Examples you can find here
NSBundle *bundle = [NSBundle mainBundle];
NSString *pthpath = [bundle pathForResource:#"path" ofType:#"txt"];
NSString *content = [NSString stringWithContentsOfFile:pthpath encoding:NSUTF8StringEncoding error:nil];
array=[[NSArray alloc ]init];
array = [content componentsSeparatedByString:#"~"];
=====================================================================
here content is:
87,348~51,347~135,132~182,133~268,346~236,347~159,168~87,347#118,298~115,297~200,298~189,266~128,265~117,299#222,352~268,353~264,340~219,342~225,355#186,262~199,299~212,297~195,257~188,260
and array is:
"87,348",
"51,347",
"135,132",
"182,133",
"268,346",
"236,347",
"159,168",
"87,347#118,298",
"115,297",
"200,298",
"189,266",
"128,265",
"117,299#222,352",
"268,353",
"264,340",
"219,342",
"225,355#186,262",
"199,299",
"212,297",
"195,257",
"188,260"
But I want to again create an array by parsing with #. Please help me out...........
for (NSString *string in array) {
NSArray *subArray = [string componentsSeparatedByString:#"#"];
for (NSString *substring in subArray)
etc. etc.
(Next time try to have your question better formatted and articulated please.)
Instead of using componentsSeparatedByString:, use componentsSeparatedByCharactersInSet: and create a character set with the separators you want.
Also, you are creating an array there (array = [[NSArray alloc] init]) and when you do array = [content componentsSeparatedByString:#"#"] you are leaking the just allocated array. In general, seems like you should read more about how objects and references work.
I think from following code you may get some idea, if I understood your question correctly,
NSMutableArray *resultArray = [[NSMutableArray alloc] initWithCapacity:1];
NSArray *tempArray1 = nil;
NSArray *tempArray2 = nil;
NSString *content = #"87,348~51,347~135,132~182,133~268,346~236,347~159,168~87,347#118,298~115,297~200,298~189,266~128,265~117,299#222,352~268,353~264,340~219,342~225,355#186,262~199,299~212,297~195,257~188,260";
tempArray1 = [content componentsSeparatedByString:#"#"];
for(NSString *string in tempArray1)
{
tempArray2 = [string componentsSeparatedByString:#"~"];
[resultArray addObjectsFromArray:tempArray2];
}
NSLog(#"ResultArray :%#", resultArray);