Passing archived Data through a sharedURL - iphone

I currently have two somewhat similar apps and was looking into a way to share data across the two apps. I set up a shared url and everything and can jump from one app to the other without any problem. The problem arises when I try to pass data through the url. I have a class in both apps that are identical to one another and am relying on a NSKeyedArchiver and decoder for the encoding of them and decoding as well as encoding them in strings to pass along the url.
Having access to both sides I know that the data passed from app 1 to app 2 is untainted and arrives just as app 1 encoded it. But I can't seem to decode the data on the other side!
I encode it here:
NSURL* app2=[NSURL URLWithString:#"app2://"];
if ([[UIApplication sharedApplication] canOpenURL:app2]) {
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:[tableHelper objectAtIndex:[indexPath section]]forKey:#"TempData" ];
[archiver finishEncoding];
NSString* tmp=[[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding ] autorelease];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:#"app2://%#",[tmp stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]]];
[data release];
[archiver release];
}
I then decode it as such:
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
if (!url) {
return NO;
}
NSString *URLString = [url absoluteString];
NSString* dataString=[[URLString componentsSeparatedByString:#"app2://"] lastObject];
NSString* perString=[dataString stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSKeyedUnarchiver* unArchiver=[[NSKeyedUnarchiver alloc] initForReadingWithData:[perString dataUsingEncoding:NSASCIIStringEncoding]];
TempItem* temp=[unArchiver decodeObjectForKey:#"TempData"];
[unArchiver finishDecoding];
//...//
}
Is there more to encoding/decoding custom classes that I am missing? I do implement NSCoding in my class the problem I think is in
[perstring dataUsingEncoding:NSASCIIStringEncoding]
as it appears to always be null?
Thanks!
I checked the output after the encoding and it is as such
bplist00Ô,-T$topX$objectsX$versionY$archiverÑXTempData©
'U$nullÖ
XitemsizeXquantityUpriceV$classYconvertedTunitQ1#?ð
and after adding percent escapes
bplist00%C3%94%01%02%03%04%05%08,-T$topX$objectsX$versionY$archiver%C3%91%06%07XTempData%C2%80%01%C2%A9%09%0A%17%18%19%1A%1B%1F'U$null%C3%96%0B%0C%0D%0E%0F%10%11%12%13%14%15%16XitemsizeXquantityUpriceV$classYconvertedTunit%C2%80%03%C2%80%05%C2%80%04%C2%80%08%C2%80%06%C2%80%02Q1%23?%C3%B0%00%00%00%00%00%00%23?%C3%B0%00%00%00%00%00%00%10%01%C3%92%1C%0E%1D%1EZNS.objects%C2%A0%C2%80%07%C3%92%20!%22&X$classesZ$classname%C2%A3%23$%25%5ENSMutableArrayWNSArrayXNSObject%5ENSMutableArray%C3%92%20!(+%C2%A2)*XTempItemXNSObjectXTempItem%12%00%01%C2%86%C2%A0_%10%0FNSKeyedArchiver%00%08%00%11%00%16%00%1F%00(%002%005%00%3E%00#%00J%00P%00%5D%00f%00o%00u%00%7C%00%C2%86%00%C2%8B%00%C2%8D%00%C2%8F%00%C2%91%00%C2%93%00%C2%95%00%C2%97%00%C2%99%00%C2%A2%00%C2%AB%00%C2%AD%00%C2%B2%00%C2%BD%00%C2%BE%00%C3%80%00%C3%85%00%C3%8E%00%C3%99%00%C3%9D%00%C3%AC%00%C3%B4%00%C3%BD%01%0C%01%11%01%14%01%1D%01&%01/%014%00%00%00%00%00%00%02%01%00%00%00%00%00%00%00.%00%00%00%00%00%00%00%00%00%00%00%00%00%00%01F
I added NSLogs on the decode portion and it is the same. I am baffled...
After fixing the misplacement of the [unArchiver finishdecoding]; I now get the error
*** -[NSKeyedUnarchiver initForReadingWithData:]: data is NULL

Related

How to fix issue with unrecognized Special Character on Ipad/Iphone?

I am working on an app that gets a bunch of descriptions through xml and then after parsing puts them on the screen. I'm having a problem with some of the descriptions with apostrophes turning into question marks. What I mean is, they start out in the xml, on the output screen and in the database I get them from as an apostrophe, but then it shows up on the app as a Question mark. This doesn't always happen, but it does with the same descriptions every time. Heres an example:
This is what is in the xml/database
But it won't be easy.
After a tour of the house, you'll be
This is what shows up on the app:
But it won?t be easy.
After a tour of the house, you?ll be
I'm pretty sure that the problem is that the ipad/iphone doesn't recognize the character that it is receiving...but I have no idea how I would go about fixing it. Here is a my Parser code: I believe the xml is being sent as UTF - 8 encoding.
[whereToGetXML appendFormat:xmlID];
NSURL *URL=[[NSURL alloc] initWithString:whereToGetXML];
NSData *dataFromServer = [[NSData alloc] initWithContentsOfURL:URL];
NSLog(#"where to get xml is:%#", whereToGetXML);
// Do any additional setup after loading the view from its nib.
NSData *dataWithoutStringTag = [[NSData alloc]init];
NSXMLParser *firstParser = [[NSXMLParser alloc] initWithData: dataFromServer];
[firstParser setDelegate:self];
[firstParser parse];
//Convert the returned parsed string to data using dataUsingEncoding method. HAVE TO HAVE allowLossyConversion:YES or else it will crash on half of the states.
dataWithoutStringTag =[tempParserString dataUsingEncoding: NSASCIIStringEncoding allowLossyConversion:YES];
NSString *htmlCode = [[NSString alloc] initWithData:dataWithoutStringTag encoding:NSASCIIStringEncoding];
NSMutableString *temp = [NSMutableString stringWithString:htmlCode];
NSData *finalData = [temp dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSXMLParser* parser = [[NSXMLParser alloc] initWithData:finalData];
// NSLog(#"Data is: %#", dataWithoutStringTag);
//NSXMLParser* parser = [[NSXMLParser alloc] initWithData: dataFromServer];
[parser setDelegate: self];
//[parser setShouldResolveExternalEntities:YES];
[parser parse];
[parser release];
It's presumably because the string isn't escaped.
Try adding a backslash before each quotation mark.
\'message\'

how to send images via bluetooth in iphone programming?

I am some NSStrings, and I am just joining them and making a single NSString, then I am converting that single NSString to NSData and sending via bluetooth to other iphone
but now I have to send image with above data,
how can I achieve such concept ?
but I want to send single NSData (UIImage+NSString), how can I ????
a tutorial on how to program Bluetooth data transfer on the iPhone is here:
http://www.devx.com/wireless/Article/43502/1954
The essential part you're looking for is here:
-(IBAction) btnSend:(id) sender
{
//---convert an NSString object to NSData---
NSData* data;
NSString *str = [NSString stringWithString:txtMessage.text];
data = [str dataUsingEncoding: NSASCIIStringEncoding];
[self mySendDataToPeers:data];
}
- (void) mySendDataToPeers:(NSData *) data
{
if (currentSession)
[self.currentSession sendDataToAllPeers:data
withDataMode:GKSendDataReliable
error:nil];
}
Good luck with it!
I would recommend sending them in separate packets since an image could be quite large (send the image itself in multiple packets). But if you really want to do it all at once, try wrapping them in an NSDictionary. Encode the dictionary into NSData, and send it off.
Something like the following would work.
NSDictionary *myDict = //whatever your dict should hold here...
NSMutableData *packet = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:packet];
[archiver encodeObject:myDict forKey:#"SomeKey"];
[archiver finishEncoding];

XML answer problem

I tried to read the response data from google weather api, but german umlauts aren't shown correctly. Instead of "ö" I get "^".
I think the problem are those two lines of code:
CXMLElement *resultElement = [nodes objectAtIndex:0];
description = [[[[resultElement attributeForName:#"data"] stringValue] copy] autorelease];
How can i get data out of resultElement without stringValue?
PS: I use TouchXML to parse xml
You must be using an NSURLConnection to get your data I suppose. When you receive the data you can convert it to an NSString using appropriate encoding. E.g.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
if(xmlResponse == nil){
xmlResponse = [[NSMutableString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
}
else{
NSMutableString *temp = [[NSMutableString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
[xmlResponse appendString:temp];
[temp release];
}
}
Here xmlResponse is the NSMutableString that you can pass to your parser. I have used NSISOLatin1 encoding. You can check other kinds of encoding and see what gives you the characters correctly (NSUTF8StringEncoding should do it I suppose).You can check the API doc for a list of supported encodings.

Is it possible to store multiple objects using object archving?

Okay, of course it is possible, that's no issue. In my code I have multiple objects that I work with, and they need to be data persistent. To do that I've used object encoding and storing them in a data file. Such as:
-(NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory stringByAppendingPathComponent:kFilename];
}
And then further along in another section of code:
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
NSLog(#"Test 4");
[archiver encodeObject:playerTwo forKey:#"PlayerTwoObject"];
[archiver encodeObject:singlePlayer forKey:#"SinglePlayer"];
[archiver encodeObject:playerOne forKey:#"PlayerOneObject"];
[archiver encodeObject:settings forKey:#"Settings"];
[archiver finishEncoding];
[data writeToFile:[self dataFilePath] atomically:YES];
[singlePlayer release];
[playerOne release];
[playerTwo release];
[settings release];
And that saves the objects. I know it works, because I can take them out with this code:
unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:[[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]]];
SettingsObject *settings = [unarchiver decodeObjectForKey:#"Settings"];
Player *test = [unarchiver decodeObjectForKey:#"PlayerOneObject"];
NSLog(#"Power On Settings Test: %d,%d", [settings playerOneStartingLife], [settings singlePlayerStartingLife]);
NSLog(#"Power On Player Test: %#,%d", [test name], [test life]);
Cool! So now I can store my objects, and read them out. So this is where the issue comes in. In a different class I take out one of the objects I'm storing and work with it. Not all of them, I only read out one. And then I save it again after I change the settings. But I only save it:
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:singlePlayer forKey:#"SinglePlayer"];
[archiver finishEncoding];
[data writeToFile:[self dataFilePath] atomically:YES];
[singlePlayer release];
After I have done that, all the rest of the objects I have stored are removed. Now I'm confused, because I thought I was only editing the one key "SinglePlayer", but apparently that somehow removes the rest of them? Is that supossed to happen? I have had some issues with releasing the archiver, would that affect it at all... I don't think it would. Does anyone have some insight on this, because I don't want to have to take all of the objects out and re-encode them if I only want to edit one of them...
Thanks for your help!
You create a new archiver, with an emtpy data object. You write the SinglePlayer object in the data, but you do not store the rest of the data in the same, newly created archive.
To do so, unarchive the whole previously stored archive, then adjust the SinglePlayer object and archive and save it again.

How to log nsxmlparser

I'm parsing an xml from an url, by
rssParser = [[NSXMLParser alloc] initWithContentsOfURL:xmlURL];
[rssParser parse]
How to NSLog it so as to see the xml in console??? If i use
NSLog ("%#",rssParser);
i'm showed wit 'XMLParser x 4d562' in the console
You should set parser's delegate and process retrieved xml data in its methods. See NSXMLParserDelegate protocol reference.
You can't. The NSXMLParser class never loads the entire contents of the XML stream in memory at once (that's why it's an "NSXMLParser" and not an "NSXMLDocument"). You should download the data from the URL, and use it to instantiate your RSS parser, and also to create an NSString that you log instead:
NSData *data = [NSData dataWithContentsOfURL:xmlURL];
rssParser = [[NSXMLParser alloc] initWithData:data];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"data: %#", string);
[string release];
Please pay attention to the fact that the "initWithContentsOfURL:" methods are synchronous, and will block your UI thread until the data has downloaded. You might want to use ASIHTTPRequest or the NSURLConnection mechanism instead, with asynchronous connections.