creating an http body with construction method - iphone

I am trying to create a http body that I am going to pass in using NSURLRequest post.
I have my connection class all set up.
The thing is i have several methods that return NSStrings and UInt32's and one construction method that I want to use to put all of these methods into one http body which will be of data type format.
However I'm not sure how to call these methods that return the correct data from my construction method to gather the data into one data object.
here is some code that I have (shortened so its a little clearer)
these methods are used to return the data needed
- (UInt32) addDataVer
{
UInt32 dataVer = 0;
return dataVer;
}
- (NSString *) addReg
{
NSString *reg = [[NSString alloc] initWithString:#"abcd1"];
return reg;
}
- (NSString *) addActiv
{
NSString *activ = [[NSString alloc] initWithString:#"abcd2"];
return activ;
}
from here I'm not sure what to do, or how to get the data. I have created a construction method, that I want to use to grab the data and then I want to use that data to build a NSData object where I put the returning data into it in order.
this is my construction class
- (void) constructRequest
{
//what the heck do I call in here? lol
}
the last thing I will have to do is figure out how to put the nsdata representation of each return value into the data object... if that makes sense...
any help would be appreciated.
UPDATE::
So I figured out how to get the return value into my construction method, by following the force!
- (void) constructRequest
{
NSString *mystring = [[NSString alloc] initWithString:[self addReg]];
NSLog(#"mystring %#", mystring);
}
however I am not sure how to do this with a returning UInt32, or how to convert this in to a NSData structure

From Apple Docs on String formatting https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265-SW1
[NSString stringWithFormat:"my unsigned 32-bit int: %d", [self addDataVer]];
from Apple Docs about NSString class
To convert your entire string to data:
[myNSString dataUsingEncoding:NSUTF8StringEncoding];

Related

Objective c static method returns the same value every time

I'm writing a custom xml deserializer for an iphone app. As you can see below, I'm looping through all the list elements in the xml, I have debugged it, and with each loop there is a new and different element. The problem is that the xpath helper methods (there are similar ones to the one posted below, but for int and decimal) always returns the same value.
For example - 1st loop's xml "SomeValue" value will be "abc" and the helper method will return "abc", second item comes around and its xml "SomeValue" is "XYZ", but the helper method will still return "abc".
I'm new to iphone/objective c/memory managment so it could be any number of things. I just cant determine what the problem is :( could someone please offer some help?
-(void) deserializeAndCallback:(GDataXMLElement *)response
{
NSError * error;
NSArray *listings = [response nodesForXPath:#"//ListingSummary" error:&error];
NSMutableArray *deserializedListings = [[NSMutableArray alloc] init];
//loop through all listing elements, create a new listing object, set its values, and add
//it to the list of deserialized objects.
if(listings.count > 0)
{
for (GDataXMLElement *listingElement in listings)
{
Listing *list = [[Listing alloc] init];
//xpath helper function (shown below), just to get the value out of the xml
list.someValue = [QuickQuery getString:listingElement fromXPath:#"//SomeValue"];
[deserializedListings addObject:list];
}
}
if([super.delegate respondsToSelector: #selector(dataReady:)])
{
[super.delegate dataReady:deserializedListings];
}
}
+(NSString *) getString:(GDataXMLElement *)element fromXPath:(NSString *)xPath
{
NSError *error;
NSArray *result = [element nodesForXPath:xPath error:&error];
if(result.count > 0)
{
GDataXMLElement *singleValue = (GDataXMLElement *) [result objectAtIndex:0];
return singleValue.stringValue;
[singleValue release];
}
return nil;
[error release];
[result release];
}
EDIT: ok... I found a bit more info. Inside the helper function, the nodesForXpath method returns all the nodes from the entire xml, not just the current element I'm busy with. Does GDataXMLElement keep reference to its parent elements at all?
Example of what the xml looks like
<ListingSummary>
<SomeValue>abc</SomeValue>
</ListingSummary>
<ListingSummary>
<SomeValue>jhi</SomeValue>
</ListingSummary>
<ListingSummary>
<SomeValue>xyz</SomeValue>
</ListingSummary>
What you are seeing is correct behaviour for the XPath query you are using. You actually want a query relative to the current node, not the root of the document as you are doing.
See http://www.w3schools.com/xpath/
BTW + (NSString *)getString:(GDataXMLElement *)element fromXPath:(NSString *)xPath is a class method, not a static method.
You say that nodesForXPath: returns all the nodes from the whole document. Since you are calling that method with the same argument, #"//SomeValue", every loop, you get back the same array every time. This means that [result objectAtIndex:0] gives you the same object every time.
Also, as I mentioned in a comment, you should not be releasing singleValue, error, or result in your helper method. You don't own those and you're not responsible for their memory. On the other hand, since you create list using alloc, you do need to release it at the end of each loop; you are currently leaking a Listing object every pass.
It looks OK for me. Although the releases inside the getString:fromXPath: aren't necessary (you don't need to release parameters entered into a method or objects obtained from a NSArray. The proper way to release an object from a NSArray is removing it from the array, as for objects passed as a parameter, if you want to release it you should do it after you call the method.
The problem to your question must be somewhere else.
result.count should be [result count] since count is a method and not a property of NSArray

What is the difference between NSString = #"HELLO" and NSString getting that same string using initWithContentsOfURL

I have a string that is getting the content from URL and when I try to use it, it doesn't work the way I thought it should.
When I initialize NSString with with contents of URL like this:
NSString *strFromURL = [[NSString alloc] initWithContentsOfURL:someURLReturningTextHELLO encoding:NSUTF8StringEncoding error:nil];
NSLog(#"%#",strFromURL); // returns "HELLO" // as expected
but when I try:
if (strFromURL == #"HELLO") { NSLog(#"IT WORKS"); } // This doesn't happen
When I do the same process with:
NSString *mySimpleString = #"HELLO";
if (mySimpleString == #"HELLO") { NSLog(#"IT WORKS"); } // This works
So, my question is, how can I get content from URL that I can use later in my IF statement?
*I'm new to Objective-C. Thanks!
When you asking for if (strFromURL == #"HELLO") you're comparing equality of objects, but not strings. When you call comparison of two constant strings it works, other it fails whether strings in compared objects are equal or not.
Call if ([strFromURL isEqualToString:#"HELLO"]) instead.
With objects, the == operator tests for pointer equality. That is, the two variables are the same if the pointers both point to the same object. The string fetched from the URL is not the same object as the constant string, so it fails. You want to use NSString's isEqualToString: method, which tests for whether the strings themselves are equal rather than the pointers.
You can try to compare with a isEqualToString method

How to extract the actual NSString from json object as NSArray

I'm working with a large set of json and really just need the NSString representation of what's inside the NSArray -including all the { }
My question is this - is their a better way than simply looping through each NSArray inside the main NSArray and outputting the description one by one?
ie- the below is a start to this process but it's very brittle meaning I need to know each item inside the hat {} and this isn't something I actually care about. I just need the json string to move forward.
The working code is below (thank you in advance!)
NSString* responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSArray* json = [responseString JSONValue];
NSArray* item = [json valueForKeyPath:#"d.data"];
NSArray* hatjson = [item objectForKey:#"hat"];
NSMutableString * result = [[NSMutableString alloc] init];
for (NSObject * obj in hatjson)
{
[result appendString:[obj description]];
}
NSLog(#"the hat json is .. %#", result);
// …
NSArray* hatjson = [item objectForKey:#"hat"];
NSString *result = [hatjson JSONRepresentation];
NSLog(#"the hat json is .. %#", result);
I’m assuming you’re using SBJSON for JSON parsing. SBJSON defines a category on NSObject that includes the method
- (NSString *)JSONRepresentation;
This method returns a string with the JSON representation of a given object so long as the object is an instance of a class which SBJSON can convert to JSON (e.g. strings, numbers, arrays, dictionaries).
I'm assuming you're using the JSON library from here: https://github.com/stig/json-framework
You're complaining that the code you provided is brittle, but it sounds like, for what you want, the situation is brittle, so I think it's ok for the code that access it to be brittle, as long as you put NSAsserts in there so that you know ASAP when your assumptions have been broken.
I think the most brittle aspect of the code you've shown is that it assumes you're getting back NSArrays, when it appears from how you're accessing it that it's actually giving you NSDictionaries.
For instance, reading your code, I conclude that the responseString represents a JSON nested map looking something like this:
{ "d": { "data": { "hat": "baseball cap" } } }
The question then is "do you ever expect the value corresponding to the "hat" key to ever have more than one value?" I would genericize this code like so:
NSString* responseString = [[[NSString alloc] initWithData: responseData encoding: NSUTF8StringEncoding] autorelease];
[responseData release];
id json = [responseString JSONValue];
id hatJSONValue = [json valueForKeyPath:#"d.data.hat"];
NSString* result = nil;
if ([hatJSONValue isKindOfClass: [NSArray class]] && [hatJSONValue count] == 1)
{
result = [[hatJSONValue lastObject] description];
}
else
{
NSAssert(NO, #"Assumptions about returned JSON were wrong.");
}
NSLog(#"the hat json is .. %#", result);
Generally speaking, you always have to make tradeoffs between writing non-brittle code and getting things done. The key should be that if your code is going to make assumptions, you should assert that they're true, so if the situation ever changes, you'll know!

How to write XML files?

I want to write a not so complicated but large file within my app and be able to send it by mail (using MFMailComposeViewController)
Since NSXMLElement and related classes are not ported to iPhone SDK what options do I have for creating XML documents?
Thanks in advance.
I would recommend using KissXML. The author started in a similar situation as you and created an NSXML compatible API wrapper around libxml. He discusses the options and decisions here on his blog.
Shameless self-promotion: KSXMLWriter
Try the open source XML stream writer for iOS:
Written in Objective-C, a single .h. and .m file
One #protocol for namespace support and one for without
Example:
// allocate serializer
XMLWriter* xmlWriter = [[XMLWriter alloc]init];
// start writing XML elements
[xmlWriter writeStartElement:#"Root"];
[xmlWriter writeCharacters:#"Text content for root element"];
[xmlWriter writeEndElement];
// get the resulting XML string
NSString* xml = [xmlWriter toString];
This produces the following XML string:
<Root>Text content for root element</Root>
It's a homework exercise in NSString building. Abstractly, create a protocol like:
#protocol XmlExport
-(NSString*)xmlElementName;
-(NSString*)xmlElementData;
-(NSDictionary*)xmlAttributes;
-(NSString*)toXML;
-(NSArray*)xmlSubElements;
#end
Make sure everything you're saving implements it and build the XML with something like the following:
-(NSString*)toXML {
NSMutableString *xmlString;
NSString *returnString;
/* Opening tag */
xmlString = [[NSMutableString alloc] initWithFormat:#"<%#", [self xmlElementName]];
for (NSString *type in [self xmlAttributes]) {
[xmlString appendFormat:#" %#=\"%#\"", type, [[self xmlAttributes] valueForKey:type]];
}
[xmlString appendString:#">"];
/* Add subelements */
for (id<XmlExport> *s in [self xmlSubElements]) {
[xmlString appendString:[s toXML]];
}
/* Data */
if ([self xmlElementData]) {
[xmlString appendString:[self xmlElementData]];
}
/* Close it up */
[xmlString appendFormat:#"</%#>", [self xmlElementName]];
/* Return immutable, free temp memory */
returnString = [NSString stringWithString:xmlString];
[xmlString release]; xmlString = nil;
return returnString;
}

Crash-proof NSDictionary

I'm looking to create a "crash-proof" NSDictionary as I'm using a JSON serializer that converts a server response into an NSDictionary. As as result, sometimes the key for the dictionary is not present. Currently, this will crash the application, however I'd rather an empty NSString was returned so I can display this in the interface.
A solution could be that I check for the key every time I access the dictionary, e.g.
if([returnedDictionary objectForKey:#"key"]){
// Display [returnedDictionary objectForKey:#"key"];
}else{
// Display #"";
}
However this soon results in bloated, hard-to-read code.
I had thought about creating a custom NSDictionary object, something like:
#interface NSSafeDictionary : NSDictionary .....
that overrides objectForKey with the above statement.
Is this a satisfactory approach?
Thanks
Are you always going to want to get strings out of your dictionary or will other objects be stored in it as well? If it's only strings, I think the easiest way around this is to construct a category on NSDictionary.
#interface NSDictionary ( EmptyStrings )
- (NSString *)stringForKey:(id)aKey;
#end
#implementation NSDictionary ( EmptyStrings )
- (NSString *)stringForKey:(id)aKey {
id object = [self objectForKey:aKey];
if (object == nil ) {
return #"";
}
if ([object isKindOfClass:[NSString class]) {
return object;
} else {
return nil;
}
}
#end
Given that it comes in over the network, I would think that you would want to sanitise the data more than just checking for empty values but if not, you don't really need to inherit from NSDictionary.
A simple utility method in your class would do the trick.
Or you could create a category on NSDictionary:
#interface NSDictionary (Safe)
-(NSString*)safeStringForKey:(NSString*)key;
#end
(I'm sure you can figure out the implementation.)