Извлечь все строки, вставленные в базу данных sqlite, и отобразить в ячейках табличного представления, содержащих метки, в качестве подпредставлений с различными разделами.
Я новичок в target-c и sqlite. Я успешно вставил данные в таблицу, используя sqlite. Мой проект содержит 2 страницы
Страница "Добавить напоминание": где пользователь вводит данные и нажимает кнопку "Сохранить", которая является правой панелью навигации.
Страница "Просмотр напоминания": здесь пользователь просматривает сохраненное напоминание в ячейках представления таблицы.
т.е. 1-е напоминание в 1-й ячейке,2-е напоминание во 2-й ячейке и т. д.
Я значительно упростил задачу, указав количество разделов с помощью следующего кода. Это означает, что количество сохраненных напоминаний равно количеству разделов в таблице напоминаний.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)view
{
numTableRecords = -1;
sqlite3_stmt *statement;
if (sqlite3_open([self.databasePath UTF8String], &remindersDB) == SQLITE_OK)
{
NSString *sqlStatement = [NSString stringWithFormat: @"select count(*) from reminders"];
const char *sql = [sqlStatement cStringUsingEncoding:NSUTF8StringEncoding];
if(sqlite3_prepare_v2(remindersDB, sql, -1, &statement, NULL) == SQLITE_OK)
{
while(sqlite3_step(statement) == SQLITE_ROW)
{
numTableRecords = sqlite3_column_int(statement, 0);
}
}
else
{
printf("could not prepare statement: %s\n", sqlite3_errmsg(remindersDB));
}
}
else
{
NSLog(@"Error in Opening Database File");
}
sqlite3_close(remindersDB);
NSLog(@"Number of records = %d",numTableRecords);
return numTableRecords;
}
Основываясь на предложении, приведенном в следующей ссылке, очень похоже на мое требование:
Заполните разделы табличного представления строками таблицы в базе данных sqlite в порядке
Я взял массив и вставил извлеченные данные как объекты в массив, как показано ниже:
-(void)viewWillAppear:(BOOL)animated
{
//Retrieve the values of database
const char *dbpath = [self.databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &remindersDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:@"SELECT * FROM reminders"];
NSLog(@"Data = %@",querySQL);
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(self.remindersDB ,query_stmt , -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
ID = [[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)]autorelease];
nameField = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)]autorelease];
eventField = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)]autorelease];
dateField = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)]autorelease];
}
sqlite3_finalize(statement);
}
sqlite3_close(self.remindersDB);
}
[array addObject:ID];
[array addObject:nameField];
[array addObject:eventField];
[array addObject:dateField];
[self.theTable reloadData];
[super viewWillAppear:YES];
}
Теперь в (UITableViewCell)-клетке для строки в пути индекса я взял 4 метки и добавил их в качестве подпредставлений и назначил [array objectAtIndex:indexPath.row] для label.text, то есть:
- (UITableViewCell *)tableView:(UITableView *)view cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//NSString *CellId = [NSString stringWithFormat:@"S%1dR%1d",indexPath.section,indexPath.row];
UITableViewCell *cell = (UITableViewCell *)[view dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil] autorelease];
view.backgroundColor = [UIColor clearColor];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"reminderbutton.png"]];
label1 = [[[UILabel alloc]initWithFrame:CGRectMake(26, 3, 30, 40)]autorelease];
label1.backgroundColor = [UIColor clearColor];
label1.textColor = [UIColor whiteColor];
label2 = [[[UILabel alloc]initWithFrame:CGRectMake(45, 3, 100, 40)]autorelease];
label2.backgroundColor = [UIColor clearColor];
label2.textColor = [UIColor whiteColor];
label3 = [[[UILabel alloc]initWithFrame:CGRectMake(119, 3, 100, 40)]autorelease];
label3.backgroundColor = [UIColor clearColor];
label3.textColor = [UIColor whiteColor];
label4 = [[[UILabel alloc]initWithFrame:CGRectMake(198, 3, 120, 40)]autorelease];
label4.backgroundColor = [UIColor clearColor];
label4.textColor = [UIColor whiteColor];
}
label1.text = [array objectAtIndex:indexPath.row];
label2.text = [array objectAtIndex:indexPath.row];
label3.text = [array objectAtIndex:indexPath.row];
label4.text = [array objectAtIndex:indexPath.row];
[cell addSubview:label1];
[cell addSubview:label2];
[cell addSubview:label3];
[cell addSubview:label4];
return cell;
}
Ничего не отображается на ячейках, пожалуйста, помогите мне решить эту проблему. Очень плохо за это борюсь, так как я новичок в объективе-c, я был бы очень рад, если кто-нибудь придет с подробным объяснением и решением. Извините за вопрос если это звучит глупо
Спасибо всем заранее:)
2 ответа
Я понимаю, что вы пытаетесь сделать сейчас.
Я бы порекомендовал создать класс для хранения данных для каждого напоминания, тогда у вас может быть массив данных напоминания.
Поэтому я бы добавил новый класс в ваш проект, назвал его "Напоминание", а затем добавил свойство для каждого из ваших полей.
Ваш класс напоминания будет следующим:
Reminder.h
#import <Foundation/Foundation.h>
@interface Reminder : NSObject
@property (nonatomic, copy) NSString *reminderId;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *event;
@property (nonatomic, copy) NSString *date;
@end
и ваш файл remder.m будет:
#import "Reminder.h"
@implementation Reminder
@synthesize reminderId, name, event, date;
-(void)dealloc
{
self.reminderId = nil;
self.name = nil;
self.event = nil;
self.date = nil;
}
@end
Так что этот класс будет просто хранить данные для каждого из ваших напоминаний.
Затем в вашем контроллере представления, который показывает список напоминаний, вам нужно добавить свойство массива для хранения объектов напоминания.
Поэтому добавьте следующее свойство в свой ViewController, который показывает список напоминаний.
@property (nonatomic, retain) NSMutableArray *reminders;
убедитесь, что вы также синтезируете это в своем файле.m контроллеров представления, чтобы сделать это, добавьте эту строку кода под строкой @implementation в файле.m вашего контроллера представления:
@synthesize reminders;
Также не забудьте установить для свойства напоминалки значение nil в вашем методе dealloc, чтобы обеспечить надлежащую очистку памяти:
self.reminders = nil;
Мы будем использовать класс Reminder, который мы создали в контроллере представления, поэтому вам также необходимо импортировать ваш класс, поэтому в файле.m контроллера представления добавьте оператор импорта в верхней части файла следующим образом:
#import "Reminder.h"
Теперь ваш контроллер представления настроен и готов использовать созданный нами класс напоминаний.
Затем вам нужно добавить метод в ваш контроллер представления, который будет использоваться для загрузки ваших данных из базы данных и заполнения объектов напоминаний и массива напоминаний.
Добавьте новый метод к вашему контроллеру представления, назовите его как loadReminders
Реализация для этого метода будет:
-(void)loadReminders
{
// setup the reminders array
self.reminders = nil;
self.reminders = [[[NSMutableArray alloc] init] autorelease];
//Retrieve the values of database
const char *dbpath = [self.databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &remindersDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:@"SELECT * FROM reminders"];
NSLog(@"Data = %@",querySQL);
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(self.remindersDB ,query_stmt , -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
Reminder *loadedReminder = [[Reminder alloc] init];
loadedReminder.reminderId = [[[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)]autorelease];
loadedReminder.name = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)]autorelease];
loadedReminder.event = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)]autorelease];
loadedReminder.date = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)]autorelease];
[self.reminders addObject:loadedReminder];
[loadedReminder release];
}
sqlite3_finalize(statement);
}
sqlite3_close(self.remindersDB);
}
}
Так что этот метод делает загрузку строк из базы данных, и для каждой строки в базе данных он создает новый объект Reminder, устанавливая свойства, используя данные из строки, затем добавляя этот объект напоминания в массив напоминаний.
обратите внимание на изменение, которое я внес в ваш оригинальный код:
while (sqlite3_step(statement) == SQLITE_ROW)
оператор while будет зацикливаться и извлекать каждую строку из базы данных.
Этот новый метод (loadReminders) можно вызывать всякий раз, когда вы хотите обновить список данных, поэтому в любом месте кода, где вы в данный момент перезагружаете таблицу, вызывайте этот метод перед перезагрузкой таблицы, это обеспечит настройку массива напоминаний. готов для использования таблицы при перезагрузке. В приведенном выше примере я бы заменил ваш метод viewWillAppear следующим образом:
-(void)viewWillAppear:(BOOL)animated
{
[self loadReminders];
[self.theTable reloadData];
}
Теперь все данные настроены и готовы к использованию. А использование объекта напоминания должно значительно облегчить чтение кода в вашем tableView.
Таким образом, чтобы получить ваши данные в таблицу, замените ваши текущие методы просмотра таблицы следующим.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)view
{
return [self.reminders count];
}
Это скажет таблице создать раздел для каждого напоминания в массиве напоминаний.
Теперь из вашего описания (и ссылки) вы создаете 1 ячейку в каждом разделе. Поэтому добавьте следующий метод, чтобы сообщить tableView, что мы хотим, чтобы по 1 строке для каждого раздела
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
Прямо сейчас для cellForRowAtIndexPath замените текущий метод следующим:
- (UITableViewCell *)tableView:(UITableView *)view cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Reminder *reminderToDisplay;
reminderToDisplay = [self.reminders objectAtIndex:indexPath.section];
// Now create the cell to display the reminder data:
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil] autorelease];
view.backgroundColor = [UIColor clearColor];
cell.backgroundColor = [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:@"reminderbutton.png"]];
label1 = [[[UILabel alloc]initWithFrame:CGRectMake(26, 3, 30, 40)]autorelease];
label1.backgroundColor = [UIColor clearColor];
label1.textColor = [UIColor whiteColor];
label2 = [[[UILabel alloc]initWithFrame:CGRectMake(45, 3, 100, 40)]autorelease];
label2.backgroundColor = [UIColor clearColor];
label2.textColor = [UIColor whiteColor];
label3 = [[[UILabel alloc]initWithFrame:CGRectMake(119, 3, 100, 40)]autorelease];
label3.backgroundColor = [UIColor clearColor];
label3.textColor = [UIColor whiteColor];
label4 = [[[UILabel alloc]initWithFrame:CGRectMake(198, 3, 120, 40)]autorelease];
label4.backgroundColor = [UIColor clearColor];
label4.textColor = [UIColor whiteColor];
// Now set the labels using our reminder object
label1.text = reminderToDisplay.reminderId;
label2.text = reminderToDisplay.name;
label3.text = reminderToDisplay.event;
label4.text = reminderToDisplay.date;
// now add the labels to the cell
cell.contentView = [[UIView alloc] init] autorelease]
[cell.contentView addSubview:label1];
[cell.contentView addSubview:label2];
[cell.contentView addSubview:label3];
[cell.contentView addSubview:label4];
return cell;
}
Итак, что происходит в этом методе, сначала мы получаем напоминание для текущего раздела из массива напоминаний:
Reminder *reminderToDisplay;
reminderToDisplay = [self.reminders objectAtIndex:indexPath.section];
Следующие несколько строк должны быть знакомы, мы создаем ячейку и метки. Затем мы используем объект напоминания, чтобы установить текст метки.
Причина, по которой ваше существующее решение не работало, заключалась в том, что вы использовали indexPath.Row, а также потому, что вы используете раздел для каждого напоминания, indexPath.Row всегда будет 0, поскольку в каждом разделе у вас будет только 1 строка.
Я знаю, что это длинный пост, но, надеюсь, должен помочь вам понять, что происходит. Любые вопросы, то дайте мне знать
Вы действительно должны создать Custom UITableViewCell.
Но для быстрого решения проблемы вы можете заменить нижние строки [cell addSubview] следующими
cell.contentView = [[UIView alloc] init] autorelease]
[cell.contentView addSubview:label1];
[cell.contentView addSubview:label2];
[cell.contentView addSubview:label3];
[cell.contentView addSubview:label4];