UITableView(with sqlite3) not update - ios

i'm korean my english so simple
very very sorry
please help me
my application example phone book.
two View and tab bar with sqlite3 DB
first view is table view cell list, there are name is linked DB
second view save and find and delete phone book list with SQL query.
i want secondview save data and change tab update data list.
i coded [viewDidAppear] reloadData method
close the application re-open apllication is updated.
but not updated change the tap T_T please help me.
FirstViewController.h
#import <UIKit/UIKit.h>
#import "sqlite3.h"
#interface FirstViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
NSString *path;
NSString *dbName;
NSString *databasePath;
sqlite3 *contactDB;
}
#property (nonatomic) sqlite3 *contactDB_2;
#property (strong,nonatomic) IBOutlet UITableView *myTable;
#property (nonatomic,retain) NSMutableArray *quizs;
-(void)checkAndCreateDatabase;
-(void)readFromDatabase;
#end
FistViewController.m
#import "FirstViewController.h"
#import "person.h"
#implementation FirstViewController
#synthesize contactDB_2,myTable;
#synthesize quizs;
-(void)checkAndCreateDatabase{
NSFileManager *filemgr = [NSFileManager defaultManager];
if([filemgr fileExistsAtPath:databasePath] == NO){
const char *dbPath = [databasePath UTF8String];
if(sqlite3_open(dbPath,&contactDB) == SQLITE_OK){
char *errMsg;
const char *sql_stmt = "CREATE TABLE IF NOT EXISTS CONTACTS(ID INTEGER PRIMARY KEY AUTOINCREMENT,NAME TEXT,ADRESS TEXT, PHONE TEXT)";
sqlite3_exec(contactDB, sql_stmt, NULL, NULL, &errMsg);
sqlite3_close(contactDB);
}
}
}
-(void)readFromDatabase
{
const char *dbpath = [databasePath UTF8String];
sqlite3_stmt *statement;
if(sqlite3_open(dbpath, &contactDB)==SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT name,phone FROM contacts"];
const char *query_stmt = [querySQL UTF8String];
if(sqlite3_prepare_v2(contactDB, query_stmt, -1, &statement, NULL)==SQLITE_OK)
{
while(sqlite3_step(statement)==SQLITE_ROW){
NSString* nameField = [[NSString alloc]initWithUTF8String:(const char*)sqlite3_column_text(statement, 0)];
NSString* phoneField = [[NSString alloc]initWithUTF8String:(const char*)sqlite3_column_text(statement, 1)];
person *persons = [person alloc];
[persons setName:nameField];
[persons setPhone:phoneField];
[quizs addObject:persons];
}
sqlite3_finalize(statement);
[myTable reloadData];
}
sqlite3_close(contactDB);
}
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"전화번호목록", #"전화번호목록");
self.tabBarItem.image = [UIImage imageNamed:#"first"];
}
return self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
pragma mark - View lifecycle
- (void)viewDidLoad
{
dbName = #"contacts2.db";
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
databasePath = [documentsDir stringByAppendingPathComponent:dbName];
[self checkAndCreateDatabase];
quizs = [[NSMutableArray alloc] initWithCapacity:100];
[self readFromDatabase];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[myTable delegate];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[quizs removeAllObjects];
[self checkAndCreateDatabase];
[self readFromDatabase];
[myTable reloadData];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return quizs.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* cellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
person *p = [quizs objectAtIndex:indexPath.row];
NSString *str = [[NSString alloc]initWithFormat:#"%# %#",p.name,p.phone];
cell.textLabel.text = str;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSInteger row = indexPath.row;
NSString *temp = [[NSString alloc]initWithFormat:#"%d번쨰꺼 선택해뜸",row+1];
UIAlertView *alert =[[UIAlertView alloc] initWithTitle:#"터치" message:temp delegate:self cancelButtonTitle:nil otherButtonTitles:#"확인", nil];
[alert show];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
I want change the tab and update cell list.

Actually you can not insert the data in database in background .So until all data are inserted you have to keep application alive. If all data are saved successfully then please write reloadData code in ViewWillAppear.

Related

It seems that my App can't retrieve info from SQL database.. why? (Xcode, Objective-C)

Function to load/read database
- (void) cargarBaseDeDatos
{
BOOL exito;
NSFileManager *filemanager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#"territoriumDB.sql"];
exito = [filemanager fileExistsAtPath:writableDBPath];
if (exito) return;
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"territoriumDB.sql"];
exito = [filemanager copyItemAtPath:defaultDBPath toPath: writableDBPath error: &error];
if(!exito)
{
NSLog(#"%#", [error localizedDescription]);
}
}
List Events class, supposed to retrieve the events title from the database and display it on a table view controller, but when I run the app the rows are blank. I already linked the table view controller to the class.
#import "ListarEventoViewController.h"
#import "AppDelegate.h"
#import <sqlite3.h>
#interface ListarEventoViewController ()
{
NSMutableArray *eventos;
}
#end
#implementation ListarEventoViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
eventos = [[NSMutableArray alloc] init];
[self cargarEventos];
[self.tableView reloadData];
}
- (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
{
return [eventos count];
}
- (UITableViewCell *) tableView:(UITableView *) tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
NSDictionary *dic = [eventos objectAtIndex:indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [dic objectForKey:#"titulo"];
return cell;
}
- (void) cargarEventos
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
sqlite3 *database;
sqlite3_stmt *sentencia;
if (sqlite3_open([appDelegate.dataBasePath UTF8String], &database)==SQLITE_OK)
{
NSString *sentenciaSQL = [NSString stringWithFormat:#"select * from eventos"];
if(sqlite3_prepare_v2(database,[sentenciaSQL UTF8String], -1, &sentencia, NULL) == SQLITE_OK)
{
while (sqlite3_step(sentencia)==SQLITE_ROW)
{
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
NSString *titulo = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sentencia, 0)];
[dic setValue:titulo forKey:#"titulo"];
[eventos addObject:dic];
}
}
sqlite3_finalize(sentencia);
}
sqlite3_close(database);
}
#pragma mark - Table view delegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
}
-(CGFloat) tableView:(UITableView*)tableView heightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
return 44;
}
#end

UITableView inside a view controller

This is my View Controller, as you can see, there is a UITableView in the lower part.
I put the delegate and datasource in the .h file
#interface CourseFindrViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
While my .m file is this:
#interface CourseFindrViewController ()
{ sqlite3 *_db;}
#property (nonatomic, weak) IBOutlet UILabel *jNameLabel;
#property (weak, nonatomic) IBOutlet UITextView *jDescLabel;
#property (nonatomic, weak) IBOutlet UILabel *jEarningsLabel;
#property (weak, nonatomic) IBOutlet UITableView *cTableLabel;
#end
#implementation CourseFindrViewController
#synthesize jDetails =_jDetails;
-(void)viewWillAppear:(BOOL)animated {
_jDetails = (Jobs *)self.jDetails;
[self.jNameLabel setText:_jDetails.jName];
[self.jDescLabel setText:_jDetails.jDesc];
[self.jEarningsLabel setText:_jDetails.jEarnings];
NSLog(#"%d", _jDetails.jID);
}
- (void)viewDidUnload
{
[super viewDidUnload];
self.jNameLabel = nil;
self.jDescLabel = nil;
self.jEarningsLabel = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSArray *)course;
{
NSString *sqLiteDb = [[NSBundle mainBundle]pathForResource:#"CourseFindr" ofType:#"sqlite"];
sqlite3_stmt *statement;
NSMutableArray *retrieve = [[NSMutableArray alloc] init];
if (sqlite3_open([sqLiteDb UTF8String], &_db) != SQLITE_OK)
{
NSString *query= [NSString stringWithFormat:#"SELECT course. * FROM course INNER JOIN jobsCourse ON jobsCourse.courseID = course.cID WHERE jobsCourse.jobID = %d", _jDetails.jID];
if (sqlite3_prepare_v2(_db, [query UTF8String], -1, &statement, nil) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
int _cID = sqlite3_column_int(statement, 0);
char *cNameChars = (char *) sqlite3_column_text(statement,1);
char *cDescChars = (char *) sqlite3_column_text(statement, 2);
char *cSchoolChars = (char *) sqlite3_column_text (statement, 3);
char *cProgramChars = (char *) sqlite3_column_text(statement, 4);
NSString *_cName =cNameChars?[[NSString alloc]initWithUTF8String:cNameChars]:#"";
NSString *_cDesc = cDescChars?[[NSString alloc]initWithUTF8String:cDescChars]:#"";
NSString *_cSchool = cSchoolChars?[[NSString alloc]initWithUTF8String:cSchoolChars]:#"";
NSString *_cProgram = cProgramChars?[[NSString alloc]initWithUTF8String:cProgramChars]:#"";
Course *courses = [[Course alloc]
initWithCID:_cID
cName:_cName
cDesc:_cDesc
cSchool:_cSchool
cProgram:_cProgram];
[retrieve addObject:courses];
}
sqlite3_finalize(statement);
}
}
return retrieve;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *title1 = _jDetails.jName;
self.navigationItem.title = title1;
}
- (void)dealloc {
}
The code stops here. I added a breakpoint.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.course count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"courseCell"];
NSLog(#"Here.");
Course *courses = [self.course objectAtIndex:indexPath.row];
cell.textLabel.text =courses.cName;
cell.detailTextLabel.text =courses.cSchool;
return cell;
}
And it's still not passing the data to the table.. the table isn't appearing.
You have to add connection between table view and your datasource and delegate.
To do that simple control drag from your table view to view controller and select datasource and do the same but this time select delegate.
You must connect datasource and delegate in the xib. Plese let me know if this answer helped you.

Sending data to detailViewController not working?

I have a UITableview that I have populated with data from a database, I know what to send data to another view (the detailViewController), however I can't get it to work, right now I am sending data via the - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { method. I have two classes the UITableview class and the detail class they are below. I also have an NSObject class that holds the objects for the database. Please check it out, here's my code:
UITableView Class code.:
Header File
#import <UIKit/UIKit.h>
#import <sqlite3.h>
#interface ExerciseViewController : UITableViewController {
NSMutableArray *theauthors;
sqlite3 * db;
}
#property(nonatomic,retain) NSMutableArray *theauthors;
-(NSMutableArray *) authorList;
#end
Implementation File
#import "ExerciseViewController.h"
#import "sqlColumns.h"
#import <sqlite3.h>
#import "UIColor+FlatUI.h"
#import "ExerciseDetailViewController.h"
#interface ExerciseViewController ()
#end
#implementation ExerciseViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Abdominal";
[self authorList];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.theauthors count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"exerciseCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
sqlColumns *author = [self.theauthors objectAtIndex:indexPath.row];
UILabel *exerciseName = (UILabel *)[cell viewWithTag:101];
exerciseName.text = author.Name;
UILabel *equipment = (UILabel *)[cell viewWithTag:102];
equipment.text = author.Equipment;
NSString *string = author.Equipment;
NSString *trimmedString = [string stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceCharacterSet]];
if ([trimmedString isEqualToString:#"null"]) {
equipment.text = #"No Equipment";
}
UILabel *difficulty = (UILabel *)[cell viewWithTag:103];
difficulty.text = author.Difficulty;
if ([difficulty.text isEqualToString:#"Easy"]) {
difficulty.textColor = [UIColor emerlandColor];
}
if ([difficulty.text isEqualToString:#"Intermediate"]) {
difficulty.textColor = [UIColor belizeHoleColor];
}
if ([difficulty.text isEqualToString:#"Hard"]) {
difficulty.textColor = [UIColor alizarinColor];
}
if ([difficulty.text isEqualToString:#"Very Hard"]) {
difficulty.textColor = [UIColor alizarinColor];
}
UIImageView *cellImageView = (UIImageView *)[cell viewWithTag:100];
cellImageView.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#",author.File]];
UIView *bgColorView = [[UIView alloc] init];
bgColorView.backgroundColor = [UIColor cloudsColor];
bgColorView.layer.masksToBounds = YES;
[cell setSelectedBackgroundView:bgColorView];
return cell;
}
-(NSMutableArray *) authorList{
_theauthors = [[NSMutableArray alloc] initWithCapacity:10];
#try {
NSFileManager *fileMgr = [NSFileManager defaultManager];
NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:#"StayhealthyExercises.sqlite"];
BOOL success = [fileMgr fileExistsAtPath:dbPath];
if(!success)
{
NSLog(#"Cannot locate database file '%#'.", dbPath);
}
if(!(sqlite3_open([dbPath UTF8String], &db) == SQLITE_OK))
{
NSLog(#"An error has occured: %s", sqlite3_errmsg(db));
}
const char *query = "SELECT * FROM strengthexercises WHERE primarymuscle LIKE '%abdominal%'";
const char *sql = query;
sqlite3_stmt *sqlStatement;
if(sqlite3_prepare(db, sql, -1, &sqlStatement, NULL) != SQLITE_OK)
{
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}else{
while (sqlite3_step(sqlStatement)==SQLITE_ROW) {
sqlColumns * author = [[sqlColumns alloc] init];
author.Name = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,1)];
author.Muscle = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement,2)];
author.Description = [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 3)];
author.File= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 4)];
author.Sets= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 5)];
author.Reps= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 6)];
author.Equipment= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 7)];
author.PrimaryMuscle= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 8)];
author.SecondaryMuscle= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 9)];
author.Difficulty= [NSString stringWithUTF8String:(char *) sqlite3_column_text(sqlStatement, 10)];
[_theauthors addObject:author];
}
}
sqlite3_finalize(sqlStatement);
}
#catch (NSException *exception) {
NSLog(#"Problem with prepare statement: %s", sqlite3_errmsg(db));
}
#finally {
sqlite3_close(db);
return _theauthors;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"detail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
sqlColumns *author = [self.theauthors objectAtIndex:indexPath.row];
ExerciseDetailViewController *destViewController = segue.destinationViewController;
destViewController.exerciseImage.image = [UIImage imageNamed:author.File];
destViewController.descriptionLabel.text = author.Description;
}
}
#end
Now the DetailViewController
Header file:
#import <UIKit/UIKit.h>
#import "sqlColumns.h"
#interface ExerciseDetailViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *exerciseImage;
#property (weak, nonatomic) IBOutlet UILabel *descriptionLabel;
#property (nonatomic, strong) sqlColumns *author;
#end
Implementation File
#import "ExerciseDetailViewController.h"
#import "ExerciseViewController.h"
#interface ExerciseDetailViewController ()
#end
#implementation ExerciseDetailViewController
#synthesize exerciseImage,descriptionLabel,author;
- (void)viewDidLoad
{
[super viewDidLoad];
descriptionLabel.text = author.Description;
NSLog(#"%#",author.Description);
}
#end
Must be a small error, any help would be greatly appreciated!
I think the problem is that your outlets are nil. You can only set the text and the image after the viewDidLoad get called.
Try to save your info in other properties and after viewDidLoad get called assign this info to your label and image view.
In your prepare for segue:
destViewController.image = [UIImage imageNamed:author.File];
destViewController.text = author.Description;
In your header add those properties:
#property (strong, nonatomic) UIImage *image;
#property (strong, nonatomic) NSString *text;
Then in your viewDidLoad:
exerciseImage.image = self.image;
descriptionLabel.text = self.text;

cellForRowAtIndexPath is not called?

My cellForRowAtIndexPath does not fire everytime
I set dataSource and delegate to the file owner.
I also set referencing outlet.
I also try tbl.delegate=self; and tbl.datasource=self; but it does not work.
What can I do?
-(void)load
{
[name resignFirstResponder];
[salary resignFirstResponder];
name.text=#"";
salary.text=#"";
[tblViewController.data removeAllObjects];
NSString *insertStatement = [NSString stringWithFormat:#"select * from emp"];
sqlite3_stmt *statement;
NSString *path= [self getDBPath];
if (sqlite3_open([path UTF8String], &db) == SQLITE_OK)
{
if (sqlite3_prepare_v2(db, [insertStatement UTF8String], -1,&statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
NSMutableDictionary *record=[[NSMutableDictionary alloc]init];
NSString *nm= [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,0)];
NSString * sl= [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement,1)];
[record setValue:nm forKey:#"name"];
[record setValue:sl forKey:#"salary"];
NSLog(#"%# %#",nm,sl);
[tblViewController.data addObject:record];
NSLog(#"%#",tblViewController.data);
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
}
NSLog(#"%lu",(unsigned long)[tblViewController.data count]);
[tblViewController.tbl reloadData];
}
//This code is of tableviewcontroller.m
#import "tableViewController.h"
#import "ViewController.h"
#interface tableViewController ()
#end
#implementation tableViewController
#synthesize tbl,data;
#synthesize viewOfTable;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
NSLog(#"only for check");
[self setup];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//[self setup];
tbl.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-( NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-( NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [data count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
cell.textLabel.text=[[data objectAtIndex:indexPath.row] valueForKey:#
"name"];
cell.detailTextLabel.text=[[data objectAtIndex:indexPath.row]
valueForKey:#"salary"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//name.text =[[data objectAtIndex:indexPath.row] valueForKey:#"name"];
// salary.text=[[data objectAtIndex:indexPath.row] valueForKey:#"salary"];
}
- (void)setup
{
//Store the whole view in uiView...mac
// [[NSBundle mainBundle] loadNibNamed:#"RegistrationViewController" owner:self options:nil];
viewOfTable=[[UIView alloc]initWithFrame:self.view.frame];
[viewOfTable addSubview:self.view];
self.viewOfTable.translatesAutoresizingMaskIntoConstraints=YES;
}
Please solve my problem.
You didn't get anything then please tell me.
You need to set Table DataSource in order to tableView to construct table rows.
#import "tableViewController.h"
#import "ViewController.h"
#interface tableViewController () <UITableViewDataSource,UITableViewDelegate>
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
tbl.dataSource = self
tbl.delegate = self;
}
Or you can check if you have a fault in your data array, because if its size is 0, there are no rows in a section and no cells within these rows as well and cellForRowAtIndexPath is never called...
You should set dataSource and delegate. When you do this, check tbl. Maybe it nil?
If not check what value returns
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
If you implement
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
check it.
No more options.

Sort TableView by distance from current location

I have an SQL DB that contains Lat and Long info. I have found my current location and been able to get the distance of each location from my current location. I can get my tableview to show this distance, but know I want to sort that tableview so the closest are listed first.
My thought is I will need to add the distance to my SQL DB data, sort that some how and then display that info back to the tableview.
My thought is I would do all of this within my TableView. Looking for guidance on how to do this and if I should be doing it in the tableview.
#import "TulsaMasterViewController.h"
#import "TulsaDetailViewController.h"
#import "Bars.h"
#import "BarDatabase.h"
#implementation TulsaMasterViewController
#synthesize barArray = _barArray;
#synthesize currentLat = _currentLat;
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
currentLat = newLocation;
if (newLocation.horizontalAccuracy <= 100.0f) {
[lm stopUpdatingLocation];
}
[self.tableView reloadData];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
NSString *msg = [[NSString alloc]initWithString:#"Error obtaining location"];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Error" message:msg delegate:nil cancelButtonTitle:#"Done" otherButtonTitles:nil];
[alert show];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.barArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//Get the object from the array.
Bars *barObj = [self.barInfo objectAtIndex:indexPath.row];
//Set the name.
cell.textLabel.text = barObj.barName;
if (currentLat == nil) {
cell.detailTextLabel.text = [NSString stringWithFormat:#"?"];
}else
{
cell.detailTextLabel.text = [NSString stringWithFormat:#"%.02f", cachedDist];
}
// Set up the cell
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowDetails"]) {
TulsaDetailViewController *detailViewController = [segue destinationViewController];
detailViewController.detailItem = [self.barArray objectAtIndex:[self.tableView indexPathForSelectedRow].row];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.barArray = [BarDatabase database].barInfo;
lm = [[CLLocationManager alloc] init];
lm.delegate = self;
[lm startUpdatingLocation];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
for (Bars *barObj in barArray) {
NSString *strLat = barObj.Lat;
NSString *strLong = barObj.Long;
CLLocation *barLocation = [[CLLocation alloc] initWithLatitude:[strLat doubleValue] longitude:[strLong doubleValue]];
CLLocationDistance distance = [currentLat distanceFromLocation:barLocation]/1000;
[barArray addObject:[NSNumber numberWithDouble:distance]];
NSSortDescriptor *sort=[NSSortDescriptor sortDescriptorWithKey:#"cachedDist" ascending:YES];
[barArray sortUsingDescriptors:[NSArray arrayWithObject:sort]];
}
For reference the rest of my code
Bars.h
#import <Foundation/Foundation.h>
#interface Bars : NSObject {
NSString *barName;
NSString *barAddress;
NSString *Lat;
NSString *Long;
NSString *cachedDist;
}
#property (nonatomic, copy) NSString *barName;
#property (nonatomic, copy) NSString *barAddress;
#property (nonatomic, copy) NSString *Lat;
#property (nonatomic, copy) NSString *Long;
#property (nonatomic, copy) NSString *cachedDist;
- (id)initWithName:(NSString *)name address:(NSString *)address latitude:(NSString *)latitude longitude:(NSString *)longitude distance:(NSString *)distance;
#end
Bars.m
#import "Bars.h"
#implementation Bars
#synthesize barName = _barName;
#synthesize barAddress = _barAddress;
#synthesize Lat = _Lat;
#synthesize Long = _Long;
#synthesize cachedDist = _cachedDist;
- (id)initWithName:(NSString *)name address:(NSString *)address latitude:(NSString *)latitude longitude:(NSString *)longitude distance:(NSString *)distance;
{
if ((self = [super init])) {
self.barName = name;
self.barAddress = address;
self.Lat = latitude;
self.Long = longitude;
self.cachedDist = distance;
}
return self;
}
#end
BarDatabase.h
#import <Foundation/Foundation.h>
#import <sqlite3.h>
#interface BarDatabase : NSObject
{
sqlite3 *_database;
}
+ (BarDatabase *)database;
- (NSMutableArray *)barInfo;
#end
BarDatabase.m
#import "BarDatabase.h"
#import "Bars.h"
#implementation BarDatabase
static BarDatabase *_database;
+ (BarDatabase *)database {
if (_database == nil) {
_database = [[BarDatabase alloc] init];
}
return _database;
}
- (id)init {
if ((self = [super init])) {
NSString *sqLiteDb = [[NSBundle mainBundle] pathForResource:#"TulsaBars"
ofType:#"sqlite"];
if (sqlite3_open([sqLiteDb UTF8String], &_database) != SQLITE_OK) {
NSLog(#"Failed to open database!");
}
}
return self;
}
- (void)dealloc {
sqlite3_close(_database);
}
- (NSMutableArray *)barInfo {
NSMutableArray *retval = [[NSMutableArray alloc] init];
NSString *query = #"SELECT * FROM TulsaBars";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil)
== SQLITE_OK) {
while (sqlite3_step(statement) == SQLITE_ROW) {
char *nameChars = (char *) sqlite3_column_text(statement, 1);
char *addressChars = (char *) sqlite3_column_text(statement, 2);
char *latChars = (char *) sqlite3_column_text(statement, 8);
char *longChars = (char *) sqlite3_column_text(statement, 9);
NSString *name = [[NSString alloc] initWithUTF8String:nameChars];
NSString *address = [[NSString alloc] initWithUTF8String:addressChars];
NSString *latitude = [[NSString alloc] initWithUTF8String:latChars];
NSString *longitude = [[NSString alloc] initWithUTF8String:longChars];
Bars *info = [[Bars alloc]
initWithName:name address:address latitude:latitude longitude:longitude];
[retval addObject:info];
}
sqlite3_finalize(statement);
}
return retval;
}
#end
Hrm. There should be no sorting happening inside cellForRowAtIndexPath. It's too late in the game. If each cell is 1 bar, and the bars should be sorted by distance, I recommend achieving the sort in a lazy getter for your self.barInfo (if that's your list of bars).
I'm not sure what your model looks like, but if each bar object has a property for distance from whatever your reference point is, your sorting would look similar to what you have there.
This sorting would only happen the when the first cell is loaded (that's the "lazy" part) and then cached. So your cellForRowAtIndexPath: would just ask for the model object at it's indexPath's row, trusting that it is in the right order.
I'm not sure how much of this terminology you are familiar with, so feel free to ask clarifying questions and I will iterate on the answer.
EDIT after sharing more code:
I think you should add a #property to the bar called something like cachedDistance, and whenever you come onscreen (viewWillAppear), iterate over the bars and set their cached distance (using similar code to what you have in cellForRow...). Then implement a getter for self.barArray: -(NSArray *)barArray which essentially returns the barArray sorted using a sortDescriptor with the name of your cached distance property as it's key. This will simplify your cellForRow... code a lot.
You can then extend the logic to recalculate the distances when you get location updates, perhaps only if it is a certain distance from the previous.

Resources