Data not loading in tableView here is my description.
I am trying to add objects from API which responding me in JSON form of data into NSMutableArray but it is not loading with the tableview.
I can see the array sets ok but it does not load into tableview until I try to scroll the tableview.
It is just so annoying and cannot figure out why kindly help me to figure out.
Here is my code -
- (void)viewDidLoad {
[SVProgressHUD showWithStatus:#"Please wait ..."];
//get the bookings
[self getBookings];
[super viewDidLoad];
[self.tableView reloadData];
}
-(void) getBookings
{
uid=#"41";
bookingsList=[[NSMutableArray alloc] init];
NSString *urlAsString = [NSString stringWithFormat:#"http://www.webservice.com/cleaning/api/booking/show/%#/%d",uid,0];
NSURL *url = [[NSURL alloc] initWithString:urlAsString];
NSLog(#"%#", urlAsString);
[NSURLConnection sendAsynchronousRequest:[[NSURLRequest alloc] initWithURL:url] queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(#"URL Session Task Failed: %#", [error localizedDescription]);
}
else {
NSArray *postsFromResponse = [NSJSONSerialization JSONObjectWithData: data options:NSJSONReadingMutableContainers error:nil];
NSLog(#"Count %d", postsFromResponse.count);
NSLog(#"JSON: %#", postsFromResponse);
//remove all objects from array
[self.bookingsList removeAllObjects];
for (NSDictionary *attributes in postsFromResponse) {
booking *bk = [[booking alloc] init];
[bk setAddress:[attributes objectForKey:#"Address"]];
[bk setBookingId:[attributes objectForKey:#"BookingID"]];
[bk setServiceDate:[attributes objectForKey:#"ServiceDate"]];
[bk setClientName:[attributes objectForKey:#"ClientName"]];
[bk setStatus:[attributes objectForKey:#"Status"]];
[bk setServiceTime:[attributes objectForKey:#"ServiceTime"]];
[bk setPrice:[attributes objectForKey:#"Price"]];
[bk setCleanType:[attributes objectForKey:#"CleanType"]];
[bk setNumOfHours:[attributes objectForKey:#"NumOfHours"]];
//add to array
[self.bookingsList addObject:bk];
}
NSLog(#"Records found -%lu",(unsigned long)[bookingsList count]);
[self.tableView reloadData];
if(bookingsList.count==0)
{
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:#"No Data Alert!"
message:#"No bookings found!" delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil];
//[alertView show];
[alertView performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
}
}
}];
[SVProgressHUD dismiss];
}
#pragma mark - TableView Delegate Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Total rows - %lu", (unsigned long)[self.bookingsList count]);
return [self.bookingsList count];
}
Use This It Will Help You
- (void)viewDidLoad {
[SVProgressHUD showWithStatus:#"Please wait ..."];
//get the bookings
[self getBookings];
[super viewDidLoad];
}
-(void) getBookings
{
uid=#"41";
bookingsList=[[NSMutableArray alloc] init];
NSString *urlAsString = [NSString stringWithFormat:#"http://www.webservice.com/cleaning/api/booking/show/%#/%d",uid,0];
NSURL *url = [[NSURL alloc] initWithString:urlAsString];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:urlAsString];
[request setHTTPMethod:GET_REQUEST];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *err)
{
if (error) {
NSLog(#"URL Session Task Failed: %#", [error localizedDescription]);
}
else {
NSArray *postsFromResponse = [NSJSONSerialization JSONObjectWithData: data options:NSJSONReadingMutableContainers error:nil];
NSLog(#"Count %d", postsFromResponse.count);
NSLog(#"JSON: %#", postsFromResponse);
//remove all objects from array
[self.bookingsList removeAllObjects];
for (NSDictionary *attributes in postsFromResponse) {
booking *bk = [[booking alloc] init];
[bk setAddress:[attributes objectForKey:#"Address"]];
[bk setBookingId:[attributes objectForKey:#"BookingID"]];
[bk setServiceDate:[attributes objectForKey:#"ServiceDate"]];
[bk setClientName:[attributes objectForKey:#"ClientName"]];
[bk setStatus:[attributes objectForKey:#"Status"]];
[bk setServiceTime:[attributes objectForKey:#"ServiceTime"]];
[bk setPrice:[attributes objectForKey:#"Price"]];
[bk setCleanType:[attributes objectForKey:#"CleanType"]];
[bk setNumOfHours:[attributes objectForKey:#"NumOfHours"]];
//add to array
[self.bookingsList addObject:bk];
}
NSLog(#"Records found -%lu",(unsigned long)[bookingsList count]);
dispatch_async(dispatch_get_main_queue(),^{
[self.tableView reloadData];
});
if(bookingsList.count==0)
{
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:#"No Data Alert!"
message:#"No bookings found!" delegate:nil
cancelButtonTitle:#"OK" otherButtonTitles:nil];
//[alertView show];
[alertView performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
}
}
}];
[task resume];
[SVProgressHUD dismiss];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"Total rows - %lu", (unsigned long)[self.bookingsList count]);
return [self.bookingsList count];
}
Coding conventions: The backing variable for any property should start with an underscore. Like _bookingsList. If you don't follow that connection, we cannot know without having your complete source code where an assignment to bookingsList will store the result.
Related
I get user name and email using this (see below).
the problem, are that the login webview close, the call to initWithGraphPath:#"me" was done async, so user can see empty field by the time I get response to this call.
Is there a way to keep the facebook login webview open since the call to initWithGraphPath was completed?
Thanks!
-(void)loginButtonClicked_Facebook{
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login
logInWithReadPermissions: #[#"public_profile", #"email"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
NSLog(#"Process error");
} else if (result.isCancelled) {
NSLog(#"Cancelled");
} else {
if ([result.grantedPermissions containsObject:#"email"]){
NSLog(#"result is:%#",result);
[self fetchUserInfo];
}
}
}];
}
-(void)fetchUserInfo{
if ([FBSDKAccessToken currentAccessToken]){
NSLog(#"Token is available : %#",[[FBSDKAccessToken currentAccessToken]tokenString]);
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"id, name, email"}]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error){
NSString *userName = [result valueForKey:#"name"];
NSString *email = [result valueForKey:#"email"];
self.tfName.text=userName;
self.tfEmail.text=email;
self.tfEmailConfirmation.text=email;
NSLog(#"resultis:%#",result);
}else{
NSLog(#"Error %#",error);
}
}];
}
}
//YOURCONTROLLER.M
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>
NSString *getFbid;
NSString *getFbFirstName,*getFBlastName, *getFbemail,*getfbBirthday,*getfbGender,*getFBpHone,*getFBlocation,*getFBcountry;
- (void) loginButton: (FBSDKLoginButton *)loginButton
didCompleteWithResult: (FBSDKLoginManagerLoginResult *)result
error: (NSError *)error{
NSLog(#"facebook login button test");
}
- (void) loginButtonDidLogOut:(FBSDKLoginButton *)loginButton{
NSLog(#"facebook logout button test");
}
-(void)loginButtonClicked
{
NSUserDefaults *defFacebookData = [NSUserDefaults standardUserDefaults];
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login
logInWithReadPermissions: #[#"public_profile", #"user_friends", #"email"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
DLog(#"Process error======%#",error.description);
indicators.hidden=YES;
[indicators stopAnimating];
} else if (result.isCancelled) {
DLog(#"Cancelled");
indicators.hidden=YES;
[indicators stopAnimating];
} else {
if ([FBSDKAccessToken currentAccessToken]) {
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"id, name, link, first_name, last_name, picture.type(large), email, birthday, bio ,location ,friends ,hometown , gender ,friendlists"}]
startWithCompletionHandler:^(
FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error)
{
// NSLog(#"fetched user:%#", result);
// [self fetchingFacebookFriends];
[defFacebookData setObject:[result objectForKey:#"email"] forKey:#"fbEmail"];
[defFacebookData setObject:[result objectForKey:#"id"] forKey:#"fbID"];
//PASS ID
getFbid = [result objectForKey:#"id"];
NSLog(#"getFbid========>%#",getFbid);
//PASS FIRST NAME
getFbFirstName=[result objectForKey:#"first_name"];
NSLog(#"first======>%#",getFbFirstName);
//PASS LAST NAME
getFBlastName=[result objectForKey:#"last_name"];
NSLog(#"first======>%#",getFBlastName);
//PASS EMAIL
getFbemail=[result objectForKey:#"email"];
NSLog(#"first======>%#",getFbemail);
//PASS PHONE
getfbGender=[result objectForKey:#"gender"];
NSLog(#"first======>%#",getfbGender);
[defFacebookData setObject:[result objectForKey:#"name"] forKey:#"fbName"];
// Image
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
initWithGraphPath:[NSString stringWithFormat:#"me/picture?type=large&redirect=false"]
parameters:nil
HTTPMethod:#"GET"];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection,
id fbImageResult,
NSError *error) {
NSString *strURL = [NSString stringWithFormat:#"%#",[[fbImageResult objectForKey:#"data"] objectForKey:#"url"]];
NSLog(#"strURL=====>%#",strURL);
[defFacebookData setObject:strURL forKey:#"fbImage"];
[defFacebookData synchronize];
NSDictionary *fbdict=[NSDictionary dictionaryWithObjectsAndKeys:getFbid,#"id",getFbFirstName,#"first_name",getFBlastName,#"last_name",getFbemail,#"email",getfbGender,#"gender",strURL,#"fbImage", nil];
NSLog(#"done=========>%#",fbdict);
UIStoryboard*storyboard=[AppDelegate storyBoardType];
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
BOOL fblogin =[defaults boolForKey:#"KeyEditProfile"];
if (fblogin)
{
UIStoryboard*Storyboard=[AppDelegate storyBoardType];
DashboardVC* tabbarController = (DashboardVC*)[Storyboard instantiateViewControllerWithIdentifier:#"DashboardVCId"];
// tabbarController.dictFacebookdict =fbdict;
// tabbarController.strFBlogin =#"fbAllDataValue";
indicators.hidden=YES;
[indicators stopAnimating];
[self.navigationController pushViewController:tabbarController animated:YES];
}
else
{
EditFBVC *cpvc=(EditFBVC*)[storyboard instantiateViewControllerWithIdentifier:#"EditFBVCId"];
NSLog(#"get fb id ===%#",getFbid);
// cpvc.checkBtnclick =#"1";
cpvc.dictFacebookdict =fbdict;
cpvc.strFBlogin =#"fbAllDataValue";
indicators.hidden=YES;
[indicators stopAnimating];
[self.navigationController pushViewController:cpvc animated:YES];
} // [self facebookdataOnServer];
}];
}
else{
//[SVProgressHUD dismiss];
DLog(#"error is %#", error.description);
}
}];
}
}
}];
}
I have a snippet of some JSON which contains ShopStyle products here: https://docs.google.com/document/d/1konfjof33sgNngxIgq_sCyKmCcDda-ziXnOfUUxeKas/edit?usp=sharing
How do I go about getting the products' names and ids from the JSON? So far, I have the following code:
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:#"http://api.shopstyle.com/api/v2/products?pid=%#&fts=%#&offset=0&limit=50", apiKey, searchkeywords]];
NSLog(#"%#", URL);
[NSURLConnection sendAsynchronousRequest:[[NSURLRequest alloc] initWithURL:URL] queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
//[self.delegate fetchingGroupsFailedWithError:error];
} else {
//[self.delegate receivedGroupsJSON:data];
NSDictionary *rest_data = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
NSLog(#"rest_data = %#", rest_data);
for (NSDictionary *topComment in[rest_data objectForKey:#"products"]) {
[self processCommentThread:topComment andLevel:0];
}
NSLog(#"GET COMMENTS RETURN:%#", commentsContainer);
[self performSelectorOnMainThread:#selector(doneFormatting) withObject:nil waitUntilDone:YES];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:[NSString stringWithFormat:#"%#", rest_data] delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil, nil];
[alert show];
}
}];
/*
PSSProductQuery *productQuery = [[PSSProductQuery alloc] init];
productQuery.searchTerm = searchBar.text;
__weak typeof(self) weakSelf = self;
[[PSSClient sharedClient] searchProductsWithQuery:productQuery offset:nil limit:nil success:^(NSUInteger totalCount, NSArray *availableHistogramTypes, NSArray *products) {
weakSelf.products = products;
[resultsTableView reloadData];
NSLog(#"_products = %#", _products);
resultsTableView.hidden = NO;
} failure:^(int *operation, NSError *error) {
}];
*/
}
- (void)processCommentThread:(NSDictionary *)comments andLevel:(int)level {
#autoreleasepool {
NSMutableDictionary *comment = [[NSMutableDictionary alloc] init];
if (!([comments objectForKey:#"name"] == nil)) {
[comment setObject:[comments objectForKey:#"name"] forKey:#"name"];
}
if (!([comments objectForKey:#"id"] == nil)) {
[comment setObject:[comments objectForKey:#"id"] forKey:#"id"];
}
}
}
-(void)doneFormatting{
[myTableView reloadData];
}
I have a Login screen and I POST username and password to a login page.
The webservice gives me 2 responses if the Login user details are correct I get a response of back from the request.
{"value":1}
and if the user details are wrong I get back from request.
{"value":0}
I have been able to parse that JSON Result to give me a log output of
value: 1 or value:0
I am battling to handle the parsed json e.g
//parse out the json data
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:urlData //1
options:kNilOptions
error:&error];
NSArray* defineJsonData = [json objectForKey:#"value"]; //2
NSLog(#"value: %#", defineJsonData); //3
if ([[json objectForKey:#"value"] isEqualToNumber:[NSNumber numberWithInt:1]])
{
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
[self performSegueWithIdentifier: #"introScreenView" sender:self];
}
else {
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Wrong Credentials" message:#"Please try to login again" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
Here is the rest of my code.
- (void)myTask {
if ([userNameTextField.text isEqualToString:#""] || [passwordTextField.text isEqualToString:#""]) {
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Feilds Missing" message:#"Please Fill all the field" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
return;
}
NSString *data = [NSString stringWithFormat:#"UserName=%#&Password=%#",userNameTextField.text, passwordTextField.text];
NSData *postData = [data dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
// preaparing URL request to send data.
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSString *url = [NSString stringWithFormat:#"http://www.ddproam.co.za/Central/Account/LogOnIOS?"];
[request setURL:[NSURL URLWithString:url]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
[request setTimeoutInterval:7.0];
NSURLResponse *response;
NSError *error;
NSData *urlData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *str=[[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];
NSLog(#"Login response:%#",str);
NSHTTPCookie *cookie;
NSLog(#"name: '%#'\n", [cookie name]);
for (NSHTTPCookie *cookie in [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies])
{
NSLog(#"name: '%#'\n", [cookie name]);
NSLog(#"value: '%#'\n", [cookie value]);
NSLog(#"domain: '%#'\n", [cookie domain]);
NSLog(#"path: '%#'\n", [cookie path]);
}
//parse out the json data
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:urlData //1
options:kNilOptions
error:&error];
NSArray* defineJsonData = [json objectForKey:#"value"]; //2
NSLog(#"value: %#", defineJsonData); //3
if ([defineJsonData isEqual:0])
{
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Wrong Credentials" message:#"Please try to login again" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
else {
HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"37x-Checkmark.png"]];
HUD.mode = MBProgressHUDModeCustomView;
[HUD hide:YES afterDelay:0];
[self performSegueWithIdentifier: #"introScreenView" sender:self];
}
if (theConnection) {
}
}
If response from the server is really just {"value":1}, then you correctly parse JSON to dictionary using NSJSONSerialization.
However under value key, there is an instance of NSNumber, not NSArray.
Your code to retrieve value and check it should look like this:
NSNumber *defineJsonData = [json objectForKey:#"value"];
NSLog(#"value: %#", defineJsonData);
if ([defineJsonData integerValue] == 0) {
NSLog(#"Wrong credentials");
}
else {
NSLog(#"Welcome :-)");
}
// Question was answered, basicly I should sleep more / code less :)
When my app starts i first load a splash screen, this splashscreen will start a dataDownload when the screen itself is done loading:
Splash.m
#implementation Splash
- (id) init
{
self = [super init];
_lblFunds = [[UILabel alloc] initWithFrame:CGRectMake(350, 330, 324,28)];
_lblFunds.numberOfLines = 1;
[_lblFunds setFont:[UIFont systemFontOfSize:24.0]];
[_lblFunds setTextAlignment: UITextAlignmentCenter];
[_lblFunds setText:#".. Fondsen .."];
[self.view addSubview:_lblFunds];
_lblObjects = [[UILabel alloc] initWithFrame:CGRectMake(350, 360, 324,28)];
_lblObjects.numberOfLines = 1;
[_lblObjects setFont:[UIFont systemFontOfSize:24.0]];
[_lblObjects setTextAlignment: UITextAlignmentCenter];
[_lblObjects setText:#".. Vastgoed Objecten .."];
[self.view addSubview:_lblObjects];
_lblCustomers = [[UILabel alloc] initWithFrame:CGRectMake(350, 390, 324,28)];
_lblCustomers.numberOfLines = 1;
[_lblCustomers setFont:[UIFont systemFontOfSize:24.0]];
[_lblCustomers setTextAlignment: UITextAlignmentCenter];
[_lblCustomers setText:#".. Clienten .."];
[self.view addSubview:_lblCustomers];
return self;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(fundsLoaded) name:#"FundsDone" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(customersLoaded) name:#"CustomersDone" object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(objectsLoaded) name:#"ObjectsDone" object:nil];
}
- (void) fundsLoaded
{
[_lblFunds setText:[NSString stringWithFormat:#"Fondsen geladen: %d",[[DataManager sharedInstance] fundsCount]]];
}
- (void) objectsLoaded
{
[_lblObjects setText:[NSString stringWithFormat:#"Vastgoed Objecten geladen: %d",[[DataManager sharedInstance] objectsCount]]];
}
- (void) customersLoaded
{
[_lblCustomers setText:[NSString stringWithFormat:#"Clienten geladen: %d",[[DataManager sharedInstance] customersCount]]];
}
- (void) viewDidLoad
{
[super viewDidLoad];
[[DataManager sharedInstance] getData];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#end
The DataManager will then proceed to use its instance of DataLoader to load and parse the data in a seperate thread, whenever data is parsed and stored away a Notification is sent from the DataLoader. If worked with the Notifications a lot before but this time it just will not work and I cannot seem to figure out why not. There is no error or anything, but the functions as set in the observers are never called. Any ideas on what is wrong are very much welcome, I have read quite a few threads on here, and other sites but haven't found my answer yet.
DataManager.m
#implementation DataManager
static DataManager* _dataManager = nil;
static DataLoader *_dataLoader = nil;
static bool _dataLoaded = FALSE;
- (int) fundsCount
{
return _dataLoader.funds_count;
}
- (int) objectsCount
{
return _dataLoader.objects_count;
}
- (int) customersCount
{
return _dataLoader.customers_count;
}
+ (DataManager *) sharedInstance{
#synchronized([DataManager class])
{
if(!_dataManager)
{
_dataManager = [[super alloc] init];
_dataLoader = [[DataLoader alloc] init];
}
return _dataManager;
}
return nil;
}
- (void) loadDataSucces
{
_dataLoaded = TRUE;
}
- (void) _getData
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if(_dataLoader)
{
[_dataLoader loadData];
} else
{
NSLog(#"DataLoader not initialized");
}
[pool drain];
}
- (void) getData
{
[NSThread detachNewThreadSelector:#selector(_getData) toTarget:self withObject:nil];
}
#end
DataLoader.m
- (void) parseData: (NSString *) jsonString
{
NSError *err;
SBJsonParser *parser = [[SBJsonParser alloc] init];
id object = [parser objectWithString:jsonString error:&err];
[jsonString release];
if (!object) {
} else {
//funds
id funds = [object objectForKey:#"fondsen"];
[self deleteAllEntitiesOfType:#"Fund"];
int nr = 0;
for (NSDictionary *i in funds)
{
NSString *naam = [i objectForKey:#"naam"];
if([naam length] > 2)
{
NSManagedObjectContext *context = [(CatalogusAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
Fund *f = [NSEntityDescription insertNewObjectForEntityForName:#"Fund" inManagedObjectContext: context];
NSString *integertje = [i objectForKey:#"oid"];
int in = [integertje integerValue];
[f setOid: [NSNumber numberWithInt: in ]];
[f setNaam: naam];
NSError *error = nil;
if( ![context save: &error ])
{
NSLog(#"Error: %#", [[error userInfo] valueForKey:#"ErrorString"]);
} else
{
nr++;
}
}
}
funds_count = nr;
[[NSNotificationCenter defaultCenter] postNotificationName:#"FundsDone" object:nil];
//objects
if( true )
{
id objects = [object objectForKey:#"vastgoedobjecten"];
[self deleteAllEntitiesOfType:#"Object"];
nr = 0;
NSManagedObjectContext *context = [(CatalogusAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
for (NSDictionary *i in objects)
{
Object *o = [NSEntityDescription insertNewObjectForEntityForName:#"Object" inManagedObjectContext: context];
[o setFondsOid:[NSNumber numberWithInt: [ [i objectForKey:#"fondsOid"] integerValue] ]];
[o setOid: [NSNumber numberWithInt: [ [i objectForKey:#"oid"] integerValue] ]];
[o setAdres:[i objectForKey:#"adres"]];
[o setPostcode:[i objectForKey:#"postcode"]];
[o setPlaats: [ i objectForKey:#"plaats"]];
[o setProvincie:[i objectForKey:#"provincie"]];
[o setStatus:[i objectForKey:#"status"]];
[o setSegment:[i objectForKey:#"segment"]];
[o setOppervlakte:[NSNumber numberWithInt: [ [i objectForKey:#"oppervlakte"] integerValue] ]];
[o setBelangrijksteHuurder:[i objectForKey:#"belangrijksteHuurder"]];
[o setWeging:[i objectForKey:#"weging"]];
[o setLongitude:[NSNumber numberWithDouble: [ [i objectForKey:#"longitude"] doubleValue] ]];
[o setLatitude:[NSNumber numberWithDouble: [ [i objectForKey:#"latitude"] doubleValue] ]];
NSError *error = nil;
if( ![context save: &error ])
{
NSLog(#"Error: %#", [[error userInfo] valueForKey:#"ErrorString"]);
} else
{
nr++;
}
}
objects_count = nr;
NSLog(#"ObjectsLoaded");
[[NSNotificationCenter defaultCenter] postNotificationName:#"ObjectsDone" object:nil];
}
//customers
if( true )
{
id custs = [object objectForKey:#"klanten"];
[self deleteAllEntitiesOfType:#"Customer"];
nr = 0;
NSManagedObjectContext *context = [(CatalogusAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
for (NSDictionary *i in custs)
{
Customer *c = [NSEntityDescription insertNewObjectForEntityForName:#"Customer" inManagedObjectContext: context];
[c setOid: [NSNumber numberWithInt: [ [i objectForKey:#"oid"] integerValue] ]];
[c setFondsOid:[NSNumber numberWithInt: [ [i objectForKey:#"fondsOid"] integerValue] ]];
[c setNaam: [i objectForKey:#"naam"]];
NSError *error = nil;
if( ![context save: &error ])
{
NSLog(#"Error: %#", [[error userInfo] valueForKey:#"ErrorString"]);
} else
{
nr++;
}
}
customers_count = nr;
[[NSNotificationCenter defaultCenter] postNotificationName:#"CustomersDone" object:nil];
}
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"DataReady" object:nil];
}
- (void) loadData{
NSString *urlString = #"URL";
NSDate *startDownload = [NSDate date];
NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:urlString]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *dataFeed = [NSURLConnection sendSynchronousRequest:theRequest returningResponse:&response error:&error];
if(error){
NSString *d = [ error description ];
NSLog(#"error: %#",d);
} int bytes = [dataFeed length];
NSDate *endDownload = [NSDate date];
NSString *data = [[NSString alloc] initWithData:[NSData decompress:dataFeed] encoding:NSStringEncodingConversionExternalRepresentation];
int string = [data length];
NSDate *endDecompress = [NSDate date];
NSLog(#"Download data: %f - Decompress: %f - BytesDownloaded: %d", [endDownload timeIntervalSinceDate:startDownload], [endDecompress timeIntervalSinceDate:endDownload], bytes);
[[NSNotificationCenter defaultCenter] postNotificationName:#"DownloadDone" object:nil];
[self parseData:data];
}
In init, you should put your registration code BEFORE the return statement. Otherwise it will never run.
Cheers!
I have a singelton class which is used to pull and store all data from a Web Service. The class has an NSArray and an NSDictionary which stores the data. I then want to use this data to populate tableviews in other views.
In one of my views, within the View Did Load method, I tell the singleton to retrieve the data from the web service and store it (it successfully retrieves the data, I logged it). I then try to access the data like so:
[[ClubData initClubData] memberData];
If I try to use that to populate the table view, it crashes and keeps referencing some kind of view. One time it referenced CALayer, another time a WrapperView ??? Am I not doing something right
My Singleton:
#import "ClubData.h"
#import "JSON.h";
#implementation ClubData
#synthesize conn, response, url, api_calls, memberData, beerData, call;
static ClubData *globalClubData = nil;
#pragma mark -
#pragma mark Instance Methods
- (void)getBeerData {
}
- (void)getSingleBeer:(NSInteger *)beerID {
}
- (void)getClubData {
//check for existing data
if (memberData != nil)
return;
//init
memberData = [[NSArray alloc] init];
//create request
call = #"memberlist";
[self initRequest:#"memberlist"];
}
- (void)getMemberData:(NSInteger *)memberID {
}
- (void)parseData:(NSString *)json {
//parse based on call type
if (call == #"memberlist") {
memberData = [[NSDictionary alloc] init];
memberData = [json JSONValue];
}
//reset call
[call release];
call = nil;
}
#pragma mark -
#pragma mark Connection & Delegate
- (void)initRequest:(NSString *)type {
//build url
NSMutableString *rURL = [[NSMutableString alloc] initWithString:url];
[rURL appendString:[api_calls objectForKey:type]];
NSURL *tempURL = [[NSURL alloc] initWithString:rURL];
[rURL release];
//init request & create connection
NSURLRequest *request = [[[NSURLRequest alloc] initWithURL:tempURL] autorelease];
conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[tempURL release];
//init response
response = [[NSMutableData alloc] init];
}
//receive data
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[response appendData:data];
}
//connection complete
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//release conn
[conn release];
//parse JSON
NSString *json = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
[response release];
//parse
[self parseData:json];
[json release];
}
//connection failed
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Connection Error"
message:#"Unable to connect to network. Network required to load data."
delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
#pragma mark -
#pragma mark Singleton Control
+ (ClubData *)initClubData {
if (globalClubData == nil) {
#synchronized(self) {
globalClubData = [[super allocWithZone:NULL] init];
}
}
return globalClubData;
}
- (id)init {
if (self = [super init]) {
//set url
url = [[[NSString alloc] initWithString:#"https://myurl.com/path/to/script.php?action=get_app_data"] retain];
//possible calls
NSArray *keys = [[NSArray alloc] initWithObjects:#"beerlist", #"singlebeer", #"memberlist", nil];
NSArray *objs = [[NSArray alloc] initWithObjects:#"&subaction=beerlist", #"&subaction=singlebeer&beerID=", #"&subaction=memberlist", nil];
api_calls = [[[NSDictionary alloc] initWithObjects:objs forKeys:keys] retain];
[keys release];
[objs release];
}
return self;
}
#pragma mark -
#pragma mark Lifecycle
- (void)dealloc {
[conn release];
[response release];
[url release];
[call release];
[api_calls release];
[super dealloc];
}
#end
api_calls = [[[NSDictionary alloc] initWithObjects:objs forKeys:keys] retain];
do not retain it (you are already an owner of that object).
As for the crash - post the stack trace.
Edit: Probably found:
if (call == #"memberlist") {
memberData = [[NSDictionary alloc] init]; //remove this (it is redundant and causes leak)
memberData = [json JSONValue]; //retain this
}