0

I have an app, and I must get the info from Internet. The request to the url is in a block and this is made after that the UIViewController be appear, and that makes that my app crash on runtime because I use the info for construct the UIViewController.

I don't know how assure that the code block finish his tasks and later use the info.

*EDIT*

Now my app shows a empty table, and I dont know how make that shows the info that I get. Maybe could be with a reloadTable, but I don't know how. Help!

StoreController.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    _productData = [ProductData ProductData];
    [_productData backEndTest];
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_listOfChips count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ProductCellController *cell = (ProductCellController*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
            if (cell == nil)
            {
                NSString* nameNib = UIUserInterfaceIdiomPad == UI_USER_INTERFACE_IDIOM() ? @"ProductCellController" : @"ProductCellControllerIphone";
                NSArray *nib = [[NSBundle mainBundle] loadNibNamed:nameNib owner:self options:nil];
                cell = [nib objectAtIndex:0];
            }
            cell = (ProductCellController*)[self cellFormat:cell atTheIndex:indexPath withThelastIndex:pathToLastRow];
            cell.image.image = [UIImage imageNamed:[((Chip*)[[_productData listOfProducts] objectAtIndex:indexPath.row])image]];
            cell.title.text = [NSString stringWithFormat:@"%@", [((Chip*)[[_productData listOfProducts] objectAtIndex:indexPath.row])title]];
            cell.price.text = [NSString stringWithFormat:@"$ %@", [((Chip*)[[_productData listOfProducts] objectAtIndex:indexPath.row])price]];
            cell.amount.text = [NSString stringWithFormat:@"%@", [((Chip*)[[_productData listOfProducts] objectAtIndex:indexPath.row])quantity]];
}

ProductData.m

+(ProductData*)ProductData
{
    ProductData* data = [[ProductData alloc]init];
    return data;
}
- (void)backEndTest
{

    [Server getProductsWithCompletionHandler:^(id result, NSError* error)
     {
         if ( error )
         {
             NSLog(@"error %@", error);
         }
         else
         {
             //NSMutableArray* arrayProducts = [NSMutableArray array];
             int index = 0;
             for (NSDictionary* product in result)
             {
                 [_listOfProducts addObject:[[Products alloc] initWithProduct:[chip objectForKey:GSR_PARAM_PRODUCT_ID]
                                                          withTitle:[product objectForKey:GSR_PARAM_PRODUCT_DESCRIPTION]
                                                         numberUses:[product objectForKey:GSR_PARAM_PRODUCT_AMOUNT]
                                                          withPrice:[product objectForKey:GSR_PARAM_PRODUCT_PRICE]
                                                       withQuantity:[product objectForKey:GSR_PARAM_PRODUCT_AMOUNT]
                                                        withInAppID:[product objectForKey:GSR_PARAM_PRODUCT_IN_APP_ID]
                                                          withImage:[[self loadImages]objectAtIndex:index ]] ];                    
                 index++;
             }
         }
     }];

}

I dont have any idea that how manage the block and assure his accomplish. Any ideas? Thanks in advance!

lightless07
  • 401
  • 6
  • 17

4 Answers4

0

You can create a completion block and in the completion block, create the viewcontroller. Instead of initialising the viewcontroller before it completes downloading the data.

How to create a completion block:

Create my own completion blocks in iOS

Community
  • 1
  • 1
lakshmen
  • 28,346
  • 66
  • 178
  • 276
0

I think you can start by not loading your UIViewController until you've finished getting all your data. Alternatively, it looks like you're using a tableViewController, so just set the number of rows to zero when you open it, then when you data arrives, change the number of rows to the correct number you've downloaded.

UPDATE: Actually, if you're getting that error on this line:

 cell = [nib objectAtIndex:0];

then it looks like there's something wrong with the nib file - not there, name wrong, name capitalized, something.

Owen Hartnett
  • 5,925
  • 2
  • 19
  • 35
0

What does your - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section look like?

You should be returning the count of your listOfProducts.

When your completion block is done you'll need to call reloadData on your tableview. You'll need to pass a pointer to your tableview, or add a delegate protocol to your existing code to make that work.

EDIT

Add a delegate protocol to allow your completion block to tell the tableview to reload. Something like this:

ProductData.h

@protocol ProductDataDelegate;

@interface ProductData
@property (nonatomic, weak) id<ProductDataDelegate> delegate;
...
@end

@protocol ProductDataDelegate <NSObject>
-(void)didFinishLoading;
@end

ProductData.m

At the end of your completion block, once the load is done:

if (self.delegate != nil)
{
    [self.delegate didFinishLoading];
}

StoreController.m

Set the delegate to point to your StoreController object.

viewDidLoad()
...
_productData = [ProductData ProductData];
_productData.delegate = self;
...

And add the code to reload, assuming that StoreController is a child class of UITableViewController.

-(void)didFinishLoading()
{
    [self reloadData];
}

That should be it!

stevekohls
  • 2,214
  • 23
  • 29
  • Ohh, I think that here is my mistake! The numberOfRows was wrong, now have the count of listOfProducts. But the table is shown empty and afer of show the Table the log tell me that the data has beed load, but I dont know when I must reload the table or anything. – lightless07 Jul 25 '13 at 19:05
  • See my edit. This shows how to create a delegate protocol to handle the reload. It should be close, in case you've never created delegate protocols before. – stevekohls Jul 25 '13 at 19:33
0

Another solution can be:

in ProductData.m

- (void)viewDidLoad
{
    [super viewDidLoad];
    _productData = [ProductData ProductData];
    [self loadDataFromServer:^{
        [self.tableView reloadData];
    }];
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_listOfChips count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ProductCellController *cell = (ProductCellController*)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
            if (cell == nil)
            {
                NSString* nameNib = UIUserInterfaceIdiomPad == UI_USER_INTERFACE_IDIOM() ? @"ProductCellController" : @"ProductCellControllerIphone";
                NSArray *nib = [[NSBundle mainBundle] loadNibNamed:nameNib owner:self options:nil];
                cell = [nib objectAtIndex:0];
            }
            cell = (ProductCellController*)[self cellFormat:cell atTheIndex:indexPath withThelastIndex:pathToLastRow];
            cell.image.image = [UIImage imageNamed:[((Chip*)[[_productData listOfProducts] objectAtIndex:indexPath.row])image]];
            cell.title.text = [NSString stringWithFormat:@"%@", [((Chip*)[[_productData listOfProducts] objectAtIndex:indexPath.row])title]];
            cell.price.text = [NSString stringWithFormat:@"$ %@", [((Chip*)[[_productData listOfProducts] objectAtIndex:indexPath.row])price]];
            cell.amount.text = [NSString stringWithFormat:@"%@", [((Chip*)[[_productData listOfProducts] objectAtIndex:indexPath.row])quantity]];
}

- (void)loadDataFromServer
{

    [Server getProductsWithCompletionHandler:^(id result, NSError* error)
     {
         if ( error )
         {
             NSLog(@"error %@", error);
         }
         else
         {
             //NSMutableArray* arrayProducts = [NSMutableArray array];
             int index = 0;
             for (NSDictionary* product in result)
             {
                 [_listOfProducts addObject:[[Products alloc] initWithProduct:[chip objectForKey:GSR_PARAM_PRODUCT_ID]
                                                          withTitle:[product objectForKey:GSR_PARAM_PRODUCT_DESCRIPTION]
                                                         numberUses:[product objectForKey:GSR_PARAM_PRODUCT_AMOUNT]
                                                          withPrice:[product objectForKey:GSR_PARAM_PRODUCT_PRICE]
                                                       withQuantity:[product objectForKey:GSR_PARAM_PRODUCT_AMOUNT]
                                                        withInAppID:[product objectForKey:GSR_PARAM_PRODUCT_IN_APP_ID]
                                                          withImage:[[self loadImages]objectAtIndex:index ]] ];                    
                 index++;
             }
         }
     }];

}
lightless07
  • 401
  • 6
  • 17