I'm downloading a .plist like this:
dispatch_async(kBgQueue, ^{
NSError* error = nil;
NSData* data = [NSData dataWithContentsOfURL:kFeedURL options:NSDataReadingUncached error:&error];
if (error) {
//NSLog(#"Feed error: %#", [error localizedDescription]);
} else {
[self performSelectorOnMainThread:#selector(fetchedData:)
withObject:data waitUntilDone:YES];
}
});
But how do I convert the data back to a plist and save it to the app?
- (void)fetchedData:(NSData *)responseData {
//???
}
It's hard to tell you what to do without more information. You say you're downloading a plist, but then ask how to convert the data back to a plist. If it's a serialized plist, then you probably want to use the NSPropertyListSerialization class method, propertyListWithData:options:format:error: to convert it to a plist object. That method returns an object typed id, so you probably should log the class of the object, to see what you actually got, and then use one of the save methods from that class to save the data.
Related
I have a situation where I will be getting more than 25000 records from web service, it is sending using pagination technique.
so the problem is I just want to store the data so for that I am thinking to run it in a loop but in future records may vary (i.e 30000,50000 etc)
from backend I am getting on each page 10000 records,but i dont know how many times i have run the loop so how do I handle this problem?
-(void)vendorsListCalling:(NSInteger)pageIndex{
[[ServicesHandler new] callVendorDetailsServiceWithParams:#{#"pageno":#(pageIndex)} CompletionBLock:^(NSDictionary *response, NSError *error) {
if (error) {
NSLog(#"error log %#",error.localizedDescription);
}else{
NSDictionary *dict = response[#"params"][#"data"];
[vendorDictionay addEntriesFromDictionary:dict];
pageCount++;
[[NSUserDefaults standardUserDefaults] setObject:vendorDictionay forKey:#"vendorsDict"];
}
}];
}
above block is where i stuck .
Any suggestions would be more appreciated.
You can store data into sqlite database. And for recursive calling for service, you can modify the same method as,
-(void)vendorsListCalling:(NSInteger)pageIndex {
if (!loader) {
//Write code to Show your loader here
}
[[ServicesHandler new] callVendorDetailsServiceWithParams:#{#"pageno":#(pageIndex)} CompletionBLock:^(NSDictionary *response, NSError *error) {
if (error) {
NSLog(#"error log %#",error.localizedDescription);
//If it fails you need to call the service again with the same Index
[self vendorsListCalling:pageCount];
} else {
if (!response[#"params"][#"data"]) {
//Stop loader since you didn't received any data
} else {
NSDictionary *dict = response[#"params"][#"data"];
[vendorDictionay addEntriesFromDictionary:dict];
pageCount++;
// Store Data in database here //
//Call service with incremented Index
[self vendorsListCalling:pageCount];
}
}
}];
}
I am requesting a file representation of an NSDictionary from Parse.com (yes I know there are other more obvious ways to store dictionaries) and then in the completion block the data gets unarchived and assigned to a property.
When this code executes it never seems to return from the unarchive line. Nothing freezes, there is no error or exception. The app continues running as though everything is fine. If I set break points at the unarchiver line and the line after it, the first breakpoint gets hit but the second never does.
I can confirm that the function has returned the expected amount of data for this file.
PFFile *definitionFile = appObject[#"myFile"]; //PFFile reference from a PFObject
[definitionFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
if (data) {
//A breakpoint on the following line does fire and show that there is data being given to the unarchiver
self.pendingDefinition = (NSDictionary *) [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
//////Nothing beyond this point gets executed////////
[self handleNewDefinition];
} else {
NSLog(#"ERROR");
}
}];
As it turned out the data was being stored as a plist and I needed to use plist serialization to extract it:
if (data) {
NSError *error;
NSPropertyListFormat format;
NSDictionary* plist = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:&format error:&error];
if(!plist){
NSLog(#"Error: %#",error);
}
i try to download data from a webserver with json into my ios app.
That´s the json output
{
"responseHeader":{
"status":0,
"QTime":37,
"params":{
"wt":"json",
"q":"title:ios"
}
},
"response":{
"numFound":348,
"start":0,
"docs":[
{
"edition":"2. ed.",
"illustrated":"Not Illustrated",
"id":"BSZ117259543",
"author":"Raw, Charles",
"title":"IOS /",
"spelling":"Raw, Charles (DE-576)180904566 Do you sincerely want to be rich? span. IOS / Charles Raw; Bruce Page; Godfrey Hodgson 2. ed. São Paulo : Ed. Expressão e Cultura, 1972 XV, 496 S. Page, Bruce (DE-576)162468539 aut Hodgson, Godfrey (DE-576)161444822 aut",
"last_indexed":"2012-09-02T01:11:38Z",
"recordtype":"marc",
"title_auth":"IOS /",
"title_sort":"ios",
"title_short":"IOS /",
"fullrecord":"00985nam a22003372"
}
]
}
}
The Code of my project:
- (void)viewDidLoad
{
[super viewDidLoad];
// 1 Schritt
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
//code executed in the background
// 2
//NSData* kivaData = [NSData dataWithContentsOfURL:[NSURLURLWithString:#"http://api.kivaws.org/v1/loans/search.json?status=fundraising"]];
NSData* kivaData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://bib.flux-services.net/solr/biblio/select?q=title:ios&wt=json"]];
//3
NSDictionary* json = nil;
if (kivaData) {
json = [NSJSONSerialization JSONObjectWithData:kivaData options:kNilOptions error:nil];
}
//4
dispatch_async(dispatch_get_main_queue(), ^{
[self updateUIWithDictionary:json];
});
});
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)updateUIWithDictionary:(NSDictionary*)json {
#try {
label.text = [NSString stringWithFormat:#"%# from %#",
json[#"docs"][0][#"title"],
json[#"docs"][0][#"edition"],
//json[#"loans"][0][#"loan_amount"],
//json[#"loans"][0][#"use"],
nil
];
}
#catch (NSException *exception) {
[[[UIAlertView alloc]initWithTitle:#"Error"
message:#"Could not parse the json feed."
delegate:nil cancelButtonTitle:#"Close" otherButtonTitles:nil]show];
NSLog(#"Exception: %#", exception);
}
When I run the programm then the IPhone simulator could not display the data.
I haven´t any idea where´s the problem!?!
Have anybody a idea or a solution???
First, exceptions are for programming errors. You don't catch exceptions. If you get exceptions, your program crashes, you find the reason, you fix the code. That's how it's done in Objective-C. People might thing you are a Java programmer.
Second, an NSLog of the dictionary you received would be useful. What you printed doesn't match your code.
Third, when you get JSON data, you just check everything. You check that you've received a dictionary. You check that there is a property named "docs" and that it is an array. You check that it has at least one element. You get the first element and check that it is a dictionary. You check that the dictionary has a property "title" and a property "edition" and that they are strings and so on.
Fourth, to help keeping your sanity, define an object representing what's in the JSON data, taking a dictionary as an initialiser, and extract everything into that object. So from then on you are in safe NSObject territory.
Fifth, what on earth do you think happens when your users read "Could not parse the JSON feed"? Their poor brains will explode. Error messages are for users, not for programmers.
Hi My problem is that i am getting a response from a web service and when i parse it and add to table and reload the table view it is not refreshing . Although if i call the [table reload] in keyboard is shown it gets updated there. Could someone tell me if im missing anything
This is what i am trying to do
- (void) longPoll {
//create an autorelease pool for the thread
#autoreleasepool {
NSLog(#"polling");
VSAppDelegate *var = (VSAppDelegate*)[[UIApplication sharedApplication] delegate];
//compose the request
NSError* error = nil;
NSHTTPURLResponse* response = nil;
//send the request (will block until a response comes back)
NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"polling response is %d",response.statusCode);
//pass the response on to the handler (can also check for errors here, if you want)
[self performSelectorOnMainThread:#selector(dataReceived:) withObject:responseData waitUntilDone:YES];
}
[self performSelectorInBackground:#selector(longPoll) withObject: nil];
}
- (void) startPoll {
[self performSelectorInBackground:#selector(longPoll) withObject: nil];
}
- (void) dataReceived: (NSData*) theData
{
//process the response here
NSError *error = nil;
NSLog(#"polling data is %#",[[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding]);
NSLog(#"polling data is %#",[[theData base64EncodedString]base64DecodedString]);
NSDictionary *notifDic= [NSJSONSerialization JSONObjectWithData:theData options:kNilOptions error:&error];
//VSViewControllerSplit *split = [[VSViewControllerSplit alloc]init];
[self RecieveFunction:notifDic];
}
try it
dispatch_async(dispatch_get_main_queue(), ^{
[tablrView reloaddata];
});
The dataReceived method doesn't appear to be calling reloadData. I'll assume that RecieveFunction method does, though, but you should confirm that. It's hard to say without seeing RecieveFunction.
The more fundamental issue would appear to be that dataReceived method is creating a new instance of VSViewControllerSplit, calling its RecieveFunction method, and then letting this new VSViewControllerSplit instance fall out of scope (and if using ARC, get deallocated unless you pushed to it, presented it, etc.). You presumably don't want to create a new VSViewControllerSplit every time longPoll calls dataReceived, but rather just reference the existing instance.
I'm new to ios development.My app gets slower when i'm parsing image using json parser in ios 5.
Please could anybody help to solve this problem.
-(NSDictionary *)Getdata
{
NSString *urlString = [NSString stringWithFormat:#"url link"];
urlString = [urlString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSURL *url = [NSURL URLWithString:urlString];
NSData* data = [NSData dataWithContentsOfURL:url];
NSError* error;
NSDictionary* json;
if (data) {
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"json...%#",json);
}
if (error) {
NSLog(#"error is %#", [error localizedDescription]);
// Handle Error and return
// return;
}
return json;
}
Your description of the problem isn't exactly helpful. It's unclear to me if everything in your app is slow, or just certain operations; if you exprience a slow action and then it becomes fast again or if it continues to perform slowly.
Whatever, the general rule is to performan all network communication including the parsing of the answer on a separate thread, i.e. not on the main thread that is responsible for managing the user interface. That way the app remains responsive and appears to be fast.
If you can download the images separately, you can already display the result and put a placeholder where the image will appear. Later, when you have received the image you remove the placeholder and put the image there.
This line is probably the culprit.
NSData* data = [NSData dataWithContentsOfURL:url];
If you're calling this on the main thread (and because you haven't mentioned threads at all I suspect that you are) it will block everything and wait until the server has responded.
This is a spectacularly bad experience for the user :)
You need to do all of this on a background thread and notify the main thread when you're done. There's a couple of ways of doing this (NSOperation etc) but the simplest is just this :
// Instead of calling 'GetData', do this instead
[self performSelectorOnBackgroundThread:#selector(GetData) withObject:nil];
// You can't return anything from this because it's going to be run in the background
-(void)GetData {
...
...
// Instead of 'return json', you need to pass it back to the main thread
[self performSelectorOnMainThread:#selector(GotData:) withObject:json waitUntilDone:NO];
}
// This gets run on the main thread with the JSON that's been got and parsed in the background
- (void)GotData:(NSDictionary *)json {
// I don't know what you were doing with your JSON but you should do it here :)
}