iPhone Objective-C JSON Parser - iphone

Has anyone had issues with a size limit on a returned JSON Object using the JSON Parser that is available for the iPhone?
I am using this open-source JSON Framework (I am using the latest version)
If I reduce the size of the returned JSON my app will run just fine. If the object gets too large, the app crashes with the below error:
-JSONValue failed. Error trace is: (
Error Domain=org.brautaset.JSON.ErrorDomain Code=3 UserInfo=0x4141580 "Unrecognised leading character"
Don't be fooled though... it has nothing to do a leading character except that it seems to split the JSON at a certain size and then ends up with a random leading character because the next JSON string starts with a random character.

Looks like I was wrong. I was trying to parse the JSON in a didReceiveData callback method, which gets called multiple times as data is received. I needed to concatenate the result as it came in and then parse the JSON in connectionDidFinishLoading.
Thanks for looking.

Related

Fetching LogBook descriptors in custom firmware

I'm looking to fetch recorded data using LogBook in a custom Movesense firmware. How do I get the correct byte stream offset for the next GET call when receiving HTTP_CONTINUE?
I'm trying to implement these steps as described in DataStorage.md:
### /Logbook usage ###
To get recording from the Movesense sensors EEPROM storage, you need to:
1. Do **GET** on */Logbook/Entries*. This returns a list of LogEntry objects. If the status was HTTP_OK, the list is complete. If the result code is HTTP_CONTINUE, you must GET again with the parameter StartAfterId set to the Id of the last entry you received and you'll get the next entries.
2. Choose the Log that you are interested in and notice the Id of it.
3. Fetch the descriptors with **GET** to */Logbook/byId/<Id>/Descriptors*. This returns a bytestream with the similar HTTP_CONTINUE handling as above. However you **must** keep re-requesting the **GET** until you get error or HTTP_OK, or the Logbook service will stay "in the middle of the stream" (we hope to remove this limitation in the future).
4. Fetch the data with **GET** to */Logbook/byId/<Id>/Data*. This returns also a bytestream (just like the */Logbook/Descriptors* above).
5. Convert the data using the converter tools or classes. (To Be Continued...)
The problem is basically the same for step 3 and 4. I receive a whiteboard::ByteStream object in the onGetResult callback function but I don't know how to get the correct offset information from it.
I've found a number of different methods seemingly concerning different aspects of number of bytes in ByteStream.h (length, fullSize, transmitted, payloadSize and serializationLength) but I just can't get it working properly.
Basically I would like to do something like this in onGetResult:
if (resultCode == whiteboard::HTTP_CODE_CONTINUE) {
const whiteboard::ByteStream &byteStream = rResultData.convertTo<const whiteboard::ByteStream &>();
currentEntryOffset += byteStream.length();
asyncGet(WB_RES::LOCAL::MEM_LOGBOOK_BYID_LOGID_DESCRIPTORS(), AsyncRequestOptions::Empty, currentEntryIdToFetch, currentEntryOffset);
return;
}
The basic idea is to do the same call again.
So if you do:
asyncGet(WB_RES::LOCAL::MEM_LOGBOOK_BYID_LOGID_DESCRIPTORS(),AsyncRequestOptions::Empty, currentEntryIdToFetch);
and get the response HTTP_CONTINUE, do:
asyncGet(WB_RES::LOCAL::MEM_LOGBOOK_BYID_LOGID_DESCRIPTORS(),AsyncRequestOptions::Empty, currentEntryIdToFetch);
Until you get HTTP_CONTINUE or an error.
If the result code is HTTP_CONTINUE, you must GET again with the parameter StartAfterId set to the Id of the last entry you received and you'll get the next entries.
Might be a bit cryptic but do another asyncGet to the exact same resource until you get HTTP_OK or an http error code.
Also, note that you need to decode the data, a python script can be found here in this answer

NSJSONSerialization issue - right number of objects, all of them "invalid"

I'm using NSJSONSerialization (very cool) to decode a string from a server. When I run it through…
id theJSONObject = [NSJSONSerialization JSONObjectWithData:inData options:NSJSONReadingAllowFragments error:&jsonError];
I get back an array with 75 objects, exactly what I would expect. However, when I examine any one of those, it tells me:
(<invalid>) [2] = <error: expected ']'
So thinking this was a JSON error, I pasted the text into JSONLint, which says it's fine.
I'm new to the JSON stuff, so I'm looking for pointers on how to debug this sort of thing.
This is actually a problem with Xcode, the data is correct but the debugger incorrectly interprets it.

NSString parsing of continuous data

Good morning,
I am retrieving a stream of bytes from a serial device that connects to the iPad. Once connected the supplied SDK will call a delegate method with the bytes that have been forwarded.
The readings forwarded by the serial device via the SDK are in the following format:
!X1:000.0;
Once connected to the serial device the delegated methods will start receiving data immediately - this could be in various states of completion i.e.
:000.00;
What I need to do is establish a concrete way of splitting the readings returned from the serial device so that I can manipulate the data.
Some of the tried options are:
Simply concatenate the received strings for a fixed period and then split the NSString on the ";" character. This is a little inefficient though and does not allow me to manipulate the data dynamically
-(void)receivingDelegateMethod:(NSString *)aString {
if(counter < 60){
[self.PropertyString stringByAppendingString:aString];
}else{
NSArray *readings = [self.PropertyString componentsSeparatedByString: #";"];
}
}
Determine a starting point by looking for the "!" character and then appending the resulting substring to a NSString property. All previous calls to the delegated method will append to this property and then remove the first 10 characters.
I know there are further options such as NSScanners and RegEx but I wanted to get the opinion of the community before wasting more time of different methods.
Thanks
Make a BOOL flag that indicates that the stream has been initialized, and set it to false. When you receive the next chunk of data, check the flag first. If it is not set, skip all characters until you see an exclamation point '!'. Once you see it, discard everything in front of it, and copy the rest of the string into the buffer. If the "is initialized" flag is set, append the entire string to the buffer without skipping characters.
Once you finish the append, scan the buffer for ! and ; delimited sections. For each occurrence of that pattern, call a designated method with a complete portion of the pattern. You can get fancy, and define your own "secondary" delegate for processing pre-validated strings.
You may need to detect disconnections, and set the "is initialized" flag back to NO.

issue with array

Getting error in this line :
NSString *nmm =[narr objectAtIndex:1];
error shows :
'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]: index
(1) beyond bounds (1)'
It looks like your array only got one value (which you can accesss at index 0, not index 1).
You should probably start by checking the contents of narr at run time. It sounds like the contents aren't what you would expect them to be at the desired point in execution. Right before the line you posted in your question, use an NSLog call to log the contents of the array like this:
NSLog(#"Contents of array: %#", narr);
Then run the app and check the console after the error arises. Put some time into learning how to use NSLog, breakpoints, and the GDB console - they will end up saving you lots of frustration when debugging.
Your comments on unset's answer raise another point: Why are you storing multiple pieces of data inside the same string? Wouldn't it be easier to separate name, lname and id into separate strings and place each into its own array cell? Then you could access them using [narr objectAtIndex:] without having to worry about parsing the string every time you need one of those pieces of information.

AVAudioPlayer initialization: error code -50

I recently ran into a problem that I couldn't find discussed anywhere on the internet - I was initializing an AVAudioPlayer to play an audio file, and getting the following error:
Error Domain=NSOSStatusErrorDomain Code=-50 "Operation could not be completed. (OSStatus error -50.)
As it turns out, I had made a mistake creating my NSURL to send to the audio player init method, resulting in the NSURL object being null. Stupid mistake, pretty easy to find when debugging, but I thought I'd list it here just in case someone else does the same thing.
“ OSStatus error -50” means paramErr, an old-style Mac error code indicating a bad parameter.
Regarding the comment from Brynjar:
The Apple NSURL Class Reference describing URLWithString states
To create NSURL objects for file system paths, use
fileURLWithPath:isDirectory: instead.
I have found that using URLWithString for file system paths generates the error reported by pix0r and therefore could be another explanation for error code = -50
Make sure your NSURL is valid, or you will get error code -50 "Operation could not be completed".
I'm adding my version of the issue and solution because I encountered the error with a print statement. I think it was related to string interpolation and or trying to forcibly print nsattributedstrings. I attempted to do the following.
print("THE ARRAY COUNT IS : \(unwrappedResults.count)\n\n\n
THE FULL ARRAY IS THE FIRST WHOLE RESULT IS: \(unwrappedResults)\n\n\n \ (unwrappedResults[0])\n
THE ATTRIBUTED FULL TEXT IS: \(unwrappedResults[0].attributedFullText)\n\n\n
THE ATTRIBUTED PRIMARY TEXT IS: \(unwrappedResults[0].attributedPrimaryText)\n\n\n
THE ATTRIBUTED SECONDARY TEXT IS: \(unwrappedResults[0].attributedSecondaryText)\n\n\n")
something about this was incorrect and no print would occur. I would receive the error following errors in my console.
boringssl_metrics_log_metric_block_invoke(131) Failed to log metrics
&
boringssl_metrics_log_metric_block_invoke(133) Error Domain=NSOSStatusErrorDomain Code=-50 "Unsupported xpc type"
UserInfo={NSDescription=Unsupported xpc type}
I fixed this issue by changing the way I unwrapped/the variables values. Fundamentally I think I was trying to print something using string interpolation that could not be printed and that is what caused this error.