Parsing document received from NSURLConnection - objective-c

I use a "get" request to receive a list of a data from a server. I have all of the NSURLConnection stuff working and receive the data ok. I am running into trouble actually parsing the data.
When the data is returned it is in a format like so:
[{"item":{"name":"xxx", "address":"xxx"}, "url":"xxx", "message":"xxx"}, {"item":{"name":"xxx", "address":"xxx"}, "url":"xxx", "message":"xxx"}.....]
Right now I have tried setting up the response data as an NSXMLDocument, then setting up this:
NSString *xpathQueryString =
#"";
NSArray *newItemsNodes = [rootNode nodesForXPath:xpathQueryString error:&error];
to get the nodes and parse through. But it does not work :(
I am not sure if this is the best way to go about this or if maybe my xpathQueryString is wrong.
Any help would be very much appreciated! Thank you for your time.

The text you are receiving is formatted as JSON, so you need to you a JSON Parser, rather than an XML Parser.
In iOS 5 there is a JSON parser included (NSJSONSerialisation), but if you are targeting systems running less than iOS 5, you need to use an external parser, such as JSONKit. Although JSONKit is actually more efficient than the one included in iOS5, so you're better off using it no matter what.

Related

Why NSLog outputs garbles when logging Chinese characters?

NSLog displays unknown garble with the following code:
NSString *sampleStr = #"你好";
NSLog(sampleStr);
But it outputs:
As I send the above characters to backend, backend shows
?????
How do I fix this problem?
What the problem specifically? NSLogging or the backend one?
If the former, first of all, you should use string formatting to output strings instead of passing the NSString object directly. This must give you desired output:
NSLog(#"%#", sampleStr);
Though, I tried your code without changes in Xcode 13.1 and it gave me the desired output nevertheless. So, probably the problem is somewhere else, not in your NSLog:
NSString *sampleStr = #"你好";
// "Format string is not a string literal (potentially insecure)"
NSLog(sampleStr); // 你好
NSLog(#"%#", sampleStr); // 你好
If you mean backend as your problem, it depends on how you "send" it to backend (in a body as data, as an HTTP parameter as text, with/without escaping, etc.) and whether your backend code supports the input you provide. To answer that more precisely we should have more information.

How to convert FlutterStandardTypedData to NSArray?

I have an app written in dart which uses a channel to call a method in Objective-C. The method needs data in form of an NSArray to act. I am passing this data as Uint8List from dart but in Objective-C, it shows that it's a FlutterStandardTypedData. Is there any way to convert that to an NSArray? Thanks in advance.
You will likely have to copy it out of the FlutterStandardTypedData using something like... (Note that in this example the typed data is doubles - you presumably have bytes)
if let args = call.arguments as? Dictionary<String, Any>,
let au = args["data"] as? FlutterStandardTypedData {
au.data.withUnsafeBytes{(pointer: UnsafeRawBufferPointer) in
let doubles = pointer.bindMemory(to: Double.self)
for index in 0..<Int(au.elementCount) {
// copy to the NSArray
}
}
result(nil)
} else {
result(FlutterError.init(code: "errorProcess", message: "data or format error", details: nil))
}
I'm having issues w/ FlutterStandardTypedData as well. From what i'm reading this should be serialized "auto-magically" on the iOS side as it's a supported data type. I can see on my end, for instance, that the length of the byte buffer is the value i'm expecting. My issue is I cannot seem to access a single value of the byte data in the same method i can see the length value. "Unrecognized selector for FlutterStandardTypedData" whenever i try to access it like an array...I cannot find good documentation either. If i use a simple data type, like string, things work out just fine. I'm only getting burned by the more complex data type(s)...
I figured it out, in the plugin you have to use FlutterStandardTypedData as the data type for the array, and then you can see the .data elements on the native iOS side. Without this data type, coming in to the iOS side i could "see" the data but would get memory exceptions every time i would try to access the data(objects/elements) in the list. Xcode was previously converting my NSArray to a FlutterStandardTypedData in the IDE (even though i specified NSArray NOT FlutterStandard...) auto-magically, but again, erroring out whenever i would try to work w/ the object. Simply changing from NSArray in plugin to FlutterStandardTypedData solved my problem, just took a while to figure out b/c the documentation wasn't very clear (that i came across).

Removing non-ascii characters from NSData?

First off, I'm not exactly sure what is happening or if I fully understand it enough to describe the issue so I'll try my best.
I'm encoding a NSData object that contains json and one of the objects contains a degree symbol. We believe this what is causing the issue and would like to remove it before encoding since the problem occurs during encoding.
I have plenty of options out there for removing certain characters from strings but none from doing it from the NSData object itself. Wondering if this is even possible or if its an issue with how I'm already encoding it.
This is how the NSData object is being encoded and turned back into a NSData object to serialize it to json. Right now I'm not trying to remove the degree symbol, using Latin 1 because another character I want to use but do not need it, this probably isn't the best way to do but it works for majority of other data objects that pass through it just not this one so this needs to change.
NSString* stringISOLatin1 = [NSString stringWithCString:data.bytes encoding:NSISOLatin1StringEncoding];
NSData* dataUTF8 = [stringISOLatin1 dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:NO];
The results are a little weird, most of the time it works fine, even including the degree symbol in the text when displayed on screen. Other times after encoding the string comes back messed up at the end which makes it unable to be serialized.
Any help would be appreciated even if it just leads to a better explanation of what is happen. Thanks
The problem is likely that you are using NSString:stringWithCString:encoding: to convert your data object. This function requires the data to be null terminated. NSData objects do not have to be NULL terminated because they have an explicit length. If the NULL character is missing it will continue to read whatever there happens to be after the string, giving you either garbage at the end or possibly crash because of memory violation.
Instead try using this:
NSString *stringISOLatin1 = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];

Make Whole Request UTF-8 from NSURLSession

I am making a simple NSURLSession GET request and i am returned the right data and i am able to serialize it up to one point where the data is no longer UTF-8 so i am unable to call keys of the children.
My data looks like this:
[
{
"GeoJsonData":"{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"LineString\",\"coordinates\":[[-119.1968536376953,35.5229358991794],[-119.19696092605591,35.52019399894053],[-119.19206857681274,35.520141605030304],[-119.19204711914062,35.52003681710729],[-119.18736934661865,35.52007174643016],[-119.18730497360228,35.52213254957543],[-119.18839931488039,35.52215001378275],[-119.18842077255249,35.522813650845336],[-119.19696092605591,35.522918435143076]]}}",
"GeoJsonCenter":"{\"lat\":35.52148635814335,\"lng\":-119.1921329498291}"
},
{
"GeoJsonData":"{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-112.42687225341795,33.49409462250672],[-112.42678642272949,33.47605511894646],[-112.42549896240234,33.47605511894646],[-112.42103576660156,33.48822503770075],[-112.41022109985352,33.49438093353938],[-112.42687225341795,33.49409462250672]]]}}",
"GeoJsonCenter":"{\"lat\":33.48521802624292,\"lng\":-112.41854667663574}"
}
]
As you can see there are alot of escape characters in there and i have 85 objects in this array i need to iterate over and once i get down to the children of these objects i am not able to call those objects.
example of my code:
NSMutableArray *geoJSONData = [[NSMutableArray alloc] init];
for (NSDictionary *item in jsonArray){
[geoJSONData addObject:[item objectForKey:#"GeoJsonData"]];
}
for (NSDictionary *item in geoJSONData) {
NSLog(#"%#", [item objectForKey:#"coordinates"]);
}
the last NSLog blows up the console because it is not able to find that key "coordinates" because it is wrapped with escaped characters and i need to get those out.
Has anyone ran into this issue and whats the best way to solve this so i can have my object working fully serialized as JSON.
any help is greatly appreciated, im just getting back into Objective-c from AngularJs and last time i worked with Objective-C i used NSUrlRequest...so things have changed.
If the data that you shown is the real representation of it then you have a small issue. The value for key GeoJsonData is not an object but a string. In other words it's an object that was serialized using JSON.stringify() and added to the parent object. Quite a strange construction, that's why I'm asking if that is the real JSON representation sent by the server.
What you'll need to do before trying to access the key coordinates is to JSON parse that string to get a valid object back so you can access it's properties as a normal NSDictionary, write now is just a string.
Just use NSJSONSerialization class to decode your GeoJsonData.

Generating large NSString xml

I have a plist and i want to convert it to xml. The xml itself is going to be around 1.2mb in size. What the best way to generate this xml? Simply with a NSMutableString? I am just worried about the performance issues and wether there is a better way to generate xml.
Thanks
For those wondering, what I have right now is something like this:
NSString *xml = [NSString stringWithFormat:#"<Sheet>%#</Sheet>", [self getSheetXMLString]];
and then, in getSheetXMLString method, i have more methods like above which drill down deep until the plist is fully transversed.
Thanks again.
What do you plan to do with the XML, if it is to output over a network or write to a file then instead of creating a NSString you could just write straight out to the network/file. If you plan to do manipulation if the XML you may want to consider libxml2, which is a C library included in iOS.