【问题标题】:UITableView is not displaying my data?UITableView 不显示我的数据?
【发布时间】:2017-05-29 17:42:30
【问题描述】:

提前感谢您阅读本文并尝试帮助我解决问题。

我已经使用 sqlite 3 构建了一个数据库,我希望制作一个应用程序,我可以在其中输入产品信息(应该发送到数据库),然后在 UIViewTable 中查看。

然而,在创建了所有的类和方法之后——我的 UIViewTable 没有显示来自我的数据库的相关信息——它完全是空的?

我收到了一些反馈,说问题可能在于数据库连接不正确?

由于我的声誉很低,我只能附上 2 个链接,所以我试图展示我认为可以提供信息的最有用的屏幕截图。他们在这个问题的底部。

以下是我所有的相关文件;

sqlite3 数据库名为“StockControl.db”

//数据.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

//数据.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 - UITableView 所在的 ViewController

#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 - UIViewTable 所在的 ViewController

#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

截图

UIViewTable with Outlets || Storyboard overview

【问题讨论】:

  • 您是否为 tableViewCell 创建了 xib ?如果是,请将该笔尖注册到视图控制器。
  • 也许您应该尝试一些更高级别的数据库,例如 FMDB、Realm、CoreData、YapDatabase?
  • @MridulGupta 我还没有为 tableViewCell 制作 xib,实现一个可以提供解决方案吗?

标签: ios objective-c sqlite uitableview


【解决方案1】:

我认为 Mridul 是对的,您只是缺少一个出口,但是您可以做一些事情来帮助自己完成调试过程。

也许您已经确认您确实获得了您期望的数据 - 但您还没有说您已经检查过了。我认为进行一些调试检查或打印语句总是值得的,以确保您实际上得到了您期望的数据。

另一件事是,看起来您将为每个 tableview 设置单独的类 - 您可以通过使用一个表示类来处理所有 tableview 开销来简化很多事情,并且只需加载您需要的数据来自您的 5 个不同来源。

【讨论】:

  • 谢谢 Russel 和 Mridul。我完全没有注意到我没有为 UITableView 制作一个出口。我现在已经用插座正确更新了代码,但表格仍然是空的。我错过了一个额外的步骤吗?我已将插座命名为 tableView。但是,我是否认为 .m 文件现在可能需要修改才能修改我制作的插座?还是我已经在表格上调用的代码来显示信息?
  • 也感谢您提供有关使用 NSLogs 进行测试的信息,我将在未来牢记这一点,并尝试养成它的习惯,因为它看起来很有帮助。我对 Russell 编码还是很陌生,所以我不太确定演示类是什么,但我也觉得我的多个表的实现并不理想。我将研究演示课程以尝试了解更多信息。再次感谢您:)
  • Russell,我一直在尝试打印语句以检查内容是否正确。但是我的调试区域没有打印任何东西?我到底应该在哪里做?我应该打印什么来测试我的数据库以确保它已正确加载:)?
  • 如果您使用 print(variableToCheck) - 我通常只打印返回的记录数 - 您应该会看到它显示在 Xcode 的输出窗口中。更有用的是,在该行设置断点,然后查看所有数据
【解决方案2】:

在 readDataFromDatabase() 中有一行:

float p = sqlite3_column_int(compiledStatement, 2);

应该是 float p = sqlite3_column_float(compiledStatement, 2);

【讨论】:

  • 我尝试使用 float = sqlite3_column_float(compiledStatement, 2); 但是根据 xCode 错误,sqlite3_column_float 不是 C99 支持的代码。当我输入 sqlite3_column_ 时,它也不会显示为选项。
【解决方案3】:

感谢你们的努力!

原来是我自己的错,因为数据库中的表被命名为“stock”,而我的 sqlStatement 试图调用一个名为条目的表。更改此错误后,它显示为我想要的!

对此我深表歉意,但我感谢您的洞察力。

【讨论】:

    猜你喜欢
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-01
    • 2014-07-06
    • 1970-01-01
    • 1970-01-01
    • 2012-08-10
    相关资源
    最近更新 更多