I have a NSMutableArray and a NSString . These two are archived to NSData and add to a NSMutableData Object.
How can I access each data from NSMutableData Object.
NSData *dataArray= [NSKeyedArchiver archivedDataWithRootObject:mutableArray];
NSData *dataTouchedNumer=[NSKeyedArchiver archivedDataWithRootObject:stringValue];
NSMutableData *mutableData=[[NSMutableData alloc]init];
[mutableData appendData:dataArray];
[mutableData appendData:dataTouchedNumer];
You can't do this the way you are showing. If you append two NSData objects together into a single mutable data object, there is no way to separate them later. Try this instead:
To archive the two objects:
NSMutableArray *mutableArray = ... // your mutable array
NSString *stringValue = ... // your string
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:mutableArray forKey:#"array"];
[archiver encodeObject:stringValue forKey:#"string"];
At this point, data contains the two objects. Do what you need with the data (save it for example).
To get your objects back:
NSData *data = ... // the archived data
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
NSMutableArray *mutableArray = [unarchiver decodeObjectForKey:#"array"];
NSString *stringValue = [unarchiver decodeObjectForKey:#"string"];
According to the docs, "archivedDataWithRootObject: returns an NSData object containing the encoded form of the object graph whose root object is given." So your mutableData object contains 2 such encoded object graphs. The question is what kind of data you want to read out of mutableData. It probably does not make much sense, to read simply all bytes with [mutableData bytes], or part of it with getBytes:length: or getBytes:range:.
Related
I got some static data, not too much, maybe 50-60 counts, which is necessary for view's content, so I have to preload them into my app. The data is not plain, not appropriate for property list,and it is too small so I'm not sure if core data is fit. Any suggestion?
I think you can convert them into NSData then save into a file.
For example:
//Write
NSArray * array = #[#"1",#"2",#"3",#"4"];
NSData * data = [NSKeyedArchiver archivedDataWithRootObject:array];
[data writeToFile:yourpath atomically:YES];
//Read
NSData * data = [NSData dataWithContentsOfFile:writeToFile:yourpath];
NSArray * array = [NSKeyedUnarchiver unarchiveObjectWithData:data];
I am using iPhone JSON Web Service based app.I need to pass input parameter as an array to a JSON web Service, how can I do this?
Array Contains 12 elements.
Here am providing sample service...
input parametes for this service:
dev_id = 1;
dev_name= josh and array items (projectslist,companyidentifier)
http://www.jyoshna.com/api/developer.php?dev_id=1&dev_name=josh&(Here i need to pass the array elements)
can any help us how to pass array as a input parameter to the json service?
First you have to convert array as JSON string
NSString *requestString=[jsonParser stringWithObject:array];
convert string to data
NSData *data=[requestString dataUsingEncoding:NSUTF8StringEncoding];
set that data as request Body
[request setHTTPBody:data];
You have to serialize the array and pass as an argument. Dont forget to unserialize in server side
you will need to create an NSMutabelDictionary of your array then JSON encode it, you can then send the resulting string you your webservice however you choose. I tend to build a POST request and send it that way
NSMutableDictionary *jsonDict = [[NSMutableDictionary alloc] init];
NSMutableDictionary *tagData = [[NSMutableDictionary alloc] init];
for(int i = 0; i < array.count; i++)
{
NSString *keyString = [NSString stringWithFormat:#"key%i", i];
[tagData setObject:[array objectAtIndex:i] forKey:keyString];
}
[jsonDict setObject:tagData forKey:#"entries"];
NSData* data = [NSJSONSerialization dataWithJSONObject:jsonDict
options:NSJSONWritingPrettyPrinted error:&error];
NSString* aStr;
aStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
It is the sgtring aStr that you need to send
I have two NSData objects I want to store within a third NSData object. The idea is I want to make it easy when I later decode the larger object, to get at the two smaller objects independently of one another, without worrying about their relative sizes or datatypes.
It appears the best way to do this is to use NSKeyedArchiver to create a sort of root-level key-value structure within the larger NSData object, in which I can store the two smaller objects within separate keys. That's what I've attempted to do here:
NSData *data1Before = [#"abcdefgh" dataUsingEncoding:NSUTF8StringEncoding];
NSData *data2Before = [#"ijklmnop" dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *allData = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:allData];
[archiver encodeObject:data1Before forKey:#"key1"];
[archiver encodeObject:data2Before forKey:#"key2"];
[archiver finishEncoding];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:allData];
NSData *data1After = [unarchiver decodeObjectForKey:#"key1"];
NSData *data2After = [unarchiver decodeObjectForKey:#"key2"];
[unarchiver finishDecoding];
NSString *string1After = [NSString stringWithUTF8String:[data1After bytes]];
NSString *string2After = [NSString stringWithUTF8String:[data2After bytes]];
NSLog(#"after1: %#",string1After);
NSLog(#"after2: %#",string2After);
The problem is, when you run this code over and over, you get all sorts of different results coming from the NSLog statements- someetimes special characters get appended to the end of the strings, sometimes they're just NULL.
It appears this corruption has something to do with this "double-encoding" process I'm using. When I modify the code so that the NSKeyedArchiver just calls encodeObject directly on NSStrings, rather than on NSData objects, I can later use decodeObjectForKey and get at those strings without any problems- no corruption at all.
Is there a better way of doing this than using NSKeyedArchiver? Or am I using it incorrectly?
Thanks to rmaddy for his answer above- I just needed to replace this:
[NSString stringWithUTF8String:[data1After bytes]];
with this:
[[NSString alloc] initWithData:data1After encoding: NSUTF8StringEncoding];
and that fixed it.
I have an NSDictionary containing some objects: an NSSet of UITouches, a UIEvent, and an NSString.
When I try to encode the dictionary to NSData, the string encodes properly. I had an error with the UITouches being encoded, but I found a way to extend the class with some code so that a UITouch can be encoded. However, I still can't encode the UIEvent (which is actually a UITouchesEvent). How can I extend the UIEvent or UIInternalEvent to make them encodable to NSData?
Methods I use for encoding/decoding:
-(NSString *)stringFromDictionary:(NSDictionary *)dict{
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:dict forKey:#"dictKey"];
[archiver finishEncoding];
return [Base64 encode:data];
}
-(NSDictionary *)dictionaryFromString:(NSString *)string{
NSData *data = [[NSMutableData alloc] initWithData:[Base64 decode:string]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
NSDictionary *myDictionary = [unarchiver decodeObjectForKey:#"dictKey"];
[unarchiver finishDecoding];
return myDictionary;
}
Error I get:
-[UITouchesEvent encodeWithCoder:]: unrecognized selector sent to instance
Please let me know if I'm missing any important info regarding debugging. Thanks!
You have to have UITouch or UITouchesEvent adapt the UICoding protocol. This means it must support these methods:
- (id)initWithCoder:(NSCoder *)decoder;
- (void)encodeWithCoder:(NSCoder *)encoder;
I haven't tried this myself, but it should work if you do this in a class category. The difficulty will be to find out what you need to encode so it can be decoded again into a correct instance, if that's what you need.
I usually encode my data in a NSFileWrapper like this (I leave out the NSFileWrapper bit):
-(NSData*)encodeObject:(id<NSCoding>)o {
#autoreleasepool {
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:o forKey:#"data"];
[archiver finishEncoding];
return data;
}
}
And I usually get my data back when doing this:
- (id)decodeObjectFromWrapperWithPreferredFilename:(NSString *)p {
NSFileWrapper *wrapper = [self.fileWrapper.fileWrappers objectForKey:p];
if (!wrapper) {
NSLog(#"Unexpected error: Couldn't find %# in file wrapper!", p);
return nil;
}
NSData *data = [wrapper regularFileContents];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
NSLog(#"%#", [unarchiver decodeObjectForKey:#"data"]);
return [unarchiver decodeObjectForKey:#"data"];
}
Sometimes, I get NSData back (it is not nil), but [unarchiver decodeObjectForKey:#"data"] will return NIL. It appears as if there is no object for the key #"data" even though there should be. I guess something must have gone wrong when encoding, but I'm not sure how to trouble shoot this. Can I just take whatever is in data and encode it, not worrying if it has got the right key? I mean there should only ever be one key "data".
Why is your code so complicated :) The NSKeyedArchiver class has helper methods that will do what you want more simply :
// to turn an object into NSData
return [NSKeyedArchiver archivedDataWithRootObject:o];
// To turn NSData into your object again
return [NSKeyedUnarchiver unarchiveObjectWithData:data];