UITableView does not display my data?

advertisements

Thanks in advance for reading this and attempting to assist me in my problem.

I have used sqlite 3 to form a database and I am hoping to make an app where I can enter information of a product (which should be sent to the database) then be viewable in a UIViewTable.

However, after having created all the classes and methods - my UIViewTable does not display the relevant information from my database - it is completely empty?

I've had some feedback saying that the problem may lie in the fact the database is not being connect correctly?

As my reputation is low I can only attach 2 links, so I'm trying to show the most useful screenshots that I believe will provide information. They're at the bottom of this question.

Below are all my relevant files;

The sqlite3 database is called "StockControl.db"

//Data.h

#import <Foundation/Foundation.h>

@interface Data : NSObject
{
NSString *name;
NSNumber *price;
NSNumber *quantity;
}

@property (strong, nonatomic) NSString *name;
@property (nonatomic, strong) NSNumber *price;
@property (nonatomic, strong) NSNumber *quantity;

-(id)initWithData:(NSString*)n thePrice:(NSNumber*)p theQuantity:(NSNumber*)q;

@end

//Data.m

#import "Data.h"

 @implementation Data
 @synthesize name, price, quantity;

 -(id)initWithData:(NSString*)n thePrice:(NSNumber*)p theQuantity:(NSNumber*)q{
if(self = [super init])
{
    [self setName:n];
    [self setPrice:p];
    [self setQuantity:q];
}
return self;
}

@end

//SiteCell.h

#import <UIKit/UIKit.h>

@interface SiteCell : UITableViewCell
{
UILabel *primaryLabel;
UILabel *secondaryLabel;
UIImageView *myImageView;
}

@property (strong, nonatomic) UILabel *primaryLabel;
@property (strong, nonatomic) UILabel* secondaryLabel;
@property (strong, nonatomic) UIImageView *myImageView;

@end

//SiteCell.m

#import "SiteCell.h"

@implementation SiteCell
@synthesize primaryLabel, secondaryLabel, myImageView;

-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
    primaryLabel = [[UILabel alloc] init];
    primaryLabel.textAlignment = NSTextAlignmentLeft;
    primaryLabel.font = [UIFont systemFontOfSize:18];
    primaryLabel.backgroundColor = [UIColor clearColor];
    primaryLabel.textColor = [UIColor whiteColor];

    secondaryLabel = [[UILabel alloc] init];
    secondaryLabel.textAlignment = NSTextAlignmentLeft;
    secondaryLabel.font = [UIFont systemFontOfSize:12];
    secondaryLabel.backgroundColor = [UIColor clearColor];
    secondaryLabel.textColor = [UIColor whiteColor];

    myImageView = [[UIImageView alloc]init];

    [self.contentView addSubview:myImageView];
    [self.contentView addSubview:primaryLabel];
    [self.contentView addSubview:secondaryLabel];
}
return self;
}

-(void)layoutSubviews{
[super layoutSubviews];

CGRect frame;

frame = CGRectMake(5, 5, 40, 40);
myImageView.frame = frame;

frame = CGRectMake(110, 5, 260, 20);
primaryLabel.frame = frame;

frame = CGRectMake(110, 30, 260, 20);
secondaryLabel.frame = frame;
}

- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];

// Configure the view for the selected state
}

@end

//StockPizza.h - ViewController where the UITableView is held

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "SiteCell.h"

@interface StockPizza : UIViewController
<UITableViewDataSource, UITableViewDelegate>
{
AppDelegate *mainDelegate;
}

@property (strong, nonatomic) AppDelegate *mainDelegate;
@property (strong, nonatomic) IBOutlet UITableView *tableView;

@end

//StockPizza.m - ViewController where the UIViewTable is held

#import "StockPizza.h"
#import <UIKit/UIKit.h>
#import "Data.h"
#import "SiteCell.h"

@interface StockPizza ()

@end

@implementation StockPizza
@synthesize mainDelegate;

#pragma mark Table Methods
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [mainDelegate.stock count];
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 60;
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *cellIdentifier = @"Cell";

SiteCell *cell = (SiteCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if(cell == nil){
    cell = [[SiteCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}

NSInteger row = indexPath.row;
Data *d = [mainDelegate.stock objectAtIndex:row];
cell.primaryLabel.text = d.name;
cell.secondaryLabel.text = [d.price stringValue];

cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

return cell;
}

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSInteger row = indexPath.row;

Data *person = [mainDelegate.stock objectAtIndex:row];

NSString *title = person.name;
NSString *msg = [person.quantity stringValue];

UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:(UIAlertControllerStyleAlert)];

UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Ok" style:(UIAlertActionStyleDefault) handler:nil];

[alert addAction:ok];
[self presentViewController:alert animated:YES completion:nil];
}

#pragma mark View Methods
- (void)viewDidLoad {
[super viewDidLoad];

self.mainDelegate = (AppDelegate*)[[UIApplication sharedApplication]delegate];

UITabBar *tabBar = self.tabBarController.tabBar;

[tabBar setBarTintColor: [UIColor blackColor]];
[tabBar setTintColor: [UIColor whiteColor]];
// Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/

@end

//AppDelegate.h

#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>
{
NSString *databaseName;
NSString *databasePath;
NSMutableArray *stock;
}

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) NSString *databaseName;
@property (strong, nonatomic) NSString *databasePath;
@property (strong, nonatomic) NSMutableArray *stock;

-(void)checkAndCreateDatabase;
-(void)readDataFromDatabase;

@end

//AppDelegate.m

#import "AppDelegate.h"
#import <sqlite3.h>
#import "Data.h"

@interface AppDelegate ()

@end

@implementation AppDelegate
@synthesize databaseName, databasePath, stock;

#pragma mark Database Methods
-(void)checkAndCreateDatabase{
BOOL success;

NSFileManager *fileManager = [NSFileManager defaultManager];

success = [fileManager fileExistsAtPath:self.databasePath];

if (success)
     return;

NSString *dataBasePathFromApp = [[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:self.databaseName];

[fileManager copyItemAtPath:dataBasePathFromApp toPath:self.databasePath error:nil];
}

-(void)readDataFromDatabase{
[self.stock removeAllObjects];

sqlite3 *database;

if (sqlite3_open([self.databasePath UTF8String], &database) == SQLITE_OK) {
    char *sqlStatement = "select * from entries";
    sqlite3_stmt *compiledStatement;

    if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK){
        while(sqlite3_step(compiledStatement) == SQLITE_ROW){
            char *n = (char*)sqlite3_column_text(compiledStatement, 1);
            float p = sqlite3_column_int(compiledStatement, 2);
            int q = sqlite3_column_int(compiledStatement, 3);

            NSString *name = [NSString stringWithUTF8String:n];
            NSNumber *price = [NSNumber numberWithFloat:p];
            NSNumber *quantity = [NSNumber numberWithInt:q];

            Data *data = [[Data alloc] initWithData:name thePrice:price theQuantity:quantity];
            [self.stock addObject:data];
        }
    }
    sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
}

#pragma mark App Methods
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.stock = [[NSMutableArray alloc]init];
self.databaseName = @"StockControl.db";

NSArray * documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString * documentsDir = [documentPaths objectAtIndex:0];

self.databasePath = [documentsDir stringByAppendingPathComponent: self.databaseName];

[self checkAndCreateDatabase];
[self readDataFromDatabase];

return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}

- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

@end

Screenshots

UIViewTable with Outlets || Storyboard overview


I think Mridul is right, and you're just missing an outlet, but there are things you can do to help yourself with the debugging process.

Perhaps you have already confirmed that you are actually getting the data you expect - but you haven't said that you have checked that. I think it's always worth having some debug checks or print statements to make sure that you're actually getting the data you expect.

Another thing is, it looks like you're going to have separate classes for each of your tableviews - you can simplify things a lot by having one presentation class to handle all of the tableview overheads, and simply load the data you need from your 5 different sources.