Push Uiview and populate with data - xcode

I'm creating a simple app that stores data into a sqlite database and retrieves data from it. I'm able to store data and I'm also able to populate a UITableView with all the data, showing a field (name) in the prototype cell. What I'm trying to do now is to open a view on tap to show ALL the details. So I did set up a viewController with 3 fields to be filled in, but I don't know how to transfer data between that cell to the new view.
Here's my code:
#import "RootViewController.h"
#import "AppDelegate.h"
#import "Inserimento_Esame.h"
#import "Dettagli_Esame.h"
#interface RootViewController ()
#end
#implementation RootViewController
#synthesize nome,crediti,voto;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *docsDir;
NSArray *dirPaths;
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,
YES);
docsDir = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:
#"Esami.sqlite"]];
dataList = [[Data alloc] init:databasePath];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation
{return YES;}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [dataList getSize];
}
- (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];
}
NSDictionary *itemAtIndex = (NSDictionary *)[dataList objectAtIndex:indexPath.row];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.text = [itemAtIndex objectForKey:#"nome"];
cell.detailTextLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.text = [itemAtIndex objectForKey:#"voto"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath
*)indexPath {
[self performSegueWithIdentifier:#"DETTAGLI" sender:indexPath];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"DETTAGLI"]) {
NSLog(#"Dettagli");
Dettagli_Esame *destination = [segue destinationViewController];
NSIndexPath * myIndexPath = [self.tableView indexPathForSelectedRow];
NSDictionary *itemAtIndex = (NSDictionary *)[dataList objectAtIndex:myIndexPath.row];
destination.Dett = itemAtIndex;
// I THINK I MUST PUT HERE MY MISSING CODE
}
}
#end
EDIT3
#import "Dettagli_Esame.h"
#interface Dettagli_Esame ()
#end
#implementation Dettagli_Esame
#synthesize nome;
#synthesize crediti;
#synthesize voto;
#synthesize Dett;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{[super viewDidLoad];}
EDIT5-6:
-(void)viewDidAppear:(BOOL)animated{
NSString *docsDir;
NSArray *dirPaths;
NSLog(#"Dettagli Esame");
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,
YES);
docsDir = [dirPaths objectAtIndex:0];
databasePath = [[NSString alloc] initWithString: [docsDir stringByAppendingPathComponent:
#"Esami.sqlite"]];
dataList = [[Data alloc] init:databasePath];
nome.text = [Dett objectForKey:#"nome"];
crediti.text = [Dett objectForKey:#"crediti"];
voto.text = [Dett objectForKey:#"voto"];
NSLog(#"Dettagli Esame: %#", self.Dett);
}

You seem to be on the right track. The information that destination needs is the same that you used to populate your cell (actually, you say 3 fields but I'll assume they're all in the same dictionary), so:
NSDictionary *itemAtIndex = (NSDictionary *)[dataList objectAtIndex:myIndexPath.row];
Then you need to create a NSDictionary property in the Dettagli_Esame class and assign it, something like:
destination.displayDictionary = itemAtIndex;
These lines would go where you indicate "missing code".

Related

Xcode - Segue issues

i've been trying to get a segue to work. I've written the following... but for some reason, the ...preparesegue... method doesnt fire. I've read other related posts but i cant get it to fire, and just as importantly, the variable i'm need isnt transferred.
m file:
#implementation CountryTableViewController
-(void) getData:(NSData *) data {
NSError *error;
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
[self.tableView reloadData];
}
-(void) start {
NSURL *url = [NSURL URLWithString: URL];
NSData *data = [NSData dataWithContentsOfURL:url];
[self getData:data];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self start];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [json count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellId = #"CellIdentifier";
TableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (!cell) {
cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
}
NSDictionary *info = [json objectAtIndex:indexPath.row];
cell.TitleLabel.text = [info objectForKey:#"CountryName"];
cell.ReferenceLabel.text = [info objectForKey:#"id"];
return cell;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender tableView:(UITableView *)tableView {
//if ([segue.identifier isEqualToString:#"CountryToState"]) {
NSLog(#"TEST");
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
TableViewCell *cell = (TableViewCell *)[tableView cellForRowAtIndexPath:path];
NSString *countryRef = [[cell ReferenceLabel] text];
TableViewControllerStates *TVCS = [segue destinationViewController];
TVCS.receivedReferenceNumber = countryRef;
//}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//TableViewCell *cell = (TableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
//NSString *countryRefNumber = [[cell ReferenceLabel] text];
[self performSegueWithIdentifier:#"CountryToState" sender:tableView];
}
h file
#import <UIKit/UIKit.h>
#define URL #"http://localhost/Rs.php"
#interface CountryTableViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
NSMutableArray *json;
}
Any help appreciated; thank you in advance.

UITableView Segue

Im trying to make a small project. Could someone help me understand why the segue does not work?
#import "CarTableViewController.h"
#import "CarTableViewCell.h"
#import "CarDetailViewController.h"
#interface CarTableViewController ()
#end
#implementation CarTableViewController
#synthesize carMakes = _carMakes;
#synthesize carModels = _carModels;
#synthesize carImages = _carImages;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.carMakes = [[NSArray alloc]
initWithObjects:#"Chevy",
#"BMW",
#"Toyota",
#"Volvo",
#"Smart", nil];
self.carModels = [[NSArray alloc]
initWithObjects:#"Volt",
#"Mini",
#"Venza",
#"S60",
#"Fortwo", nil];
self.carImages = [[NSArray alloc]
initWithObjects:#"chevy_volt.jpg",
#"mini_clubman.jpg",
#"toyota_venza.jpg",
#"volvo_s60.jpg",
#"smart_fortwo.jpg", nil];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return _carModels.count;
}
#pragma mark - Table view data source
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"carTableCell";
CarTableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CarTableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.makeLabel.text = [self.carMakes
objectAtIndex: [indexPath row]];
cell.modelLabel.text = [self.carModels
objectAtIndex:[indexPath row]];
UIImage *carPhoto = [UIImage imageNamed:
[self.carImages objectAtIndex: [indexPath row]]];
cell.carImage.image = carPhoto;
return cell;
}
The code work´s fine, and loads a tableView, but I need to go to CarDetailViewControler and I´m using the following code, but it does not work.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowCarDetails"])
{
CarDetailViewController *detailViewController =
[segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView
indexPathForSelectedRow];
detailViewController.carDetailModel = [[NSArray alloc]
initWithObjects: [self.carMakes
objectAtIndex:[myIndexPath row]],
[self.carModels objectAtIndex:[myIndexPath row]],
[self.carImages objectAtIndex:[myIndexPath row]],
nil];
}
}
In the storyboard did you use a cell prototype? If so, did you control-drag from the prototype to the destination viewcontroller and create the named segue?
The method you are using requires the segue to be defined completely in the storyboard, meaning the trigger for the segue is tied to the cell prototype.
You can manually trigger a segue using:
[self performSegueWithIdentifier:#"ShowCarDetails" sender:self];
in your:
tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath as an alternative.

CustomCell in XCode not displaying value

I created a custom cell in table view that has a search bar. Text entered by users will be used to search a SQLite db and results displayed in table view. The problem I have now is that the search result is not displayed in the table view if I use custom cell but works when I use the default cell. For e.g., in code below, if I use [cell setText:currentSubLocality]; it will display the result but it will not display result if I use cell.lblG.text = currentLocation;. Please help, been struggling with it for 2 days. Thanks
#import "CustomViewController.h"
#import "FMDBDataAccess.h"
#import "locationCode.h"
#import "CustomCell.h"
#interface CustomViewController ()
#end
#implementation CustomViewController{
NSMutableArray *searchResults;}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [searchResults count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"vvv"];
if (cell==nil){
cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"vvv"];
}
if (tableView == self.searchDisplayController.searchResultsTableView)
{
locationCode *code = [[locationCode alloc] init];
code= [searchResults objectAtIndex:indexPath.row];
NSString *currentLocation = code.location;
NSString *currentSubLocality = code.subLocality
//[cell setText:currentSubLocality];
cell.lblG.text = currentLocation;
cell.lblL.text = currentSubLocality;
}
return cell;
}
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
NSString *databasePath = [[NSBundle mainBundle] pathForResource:#"spr" ofType:#"sqlite"];
FMDatabase *database = [FMDatabase databaseWithPath:databasePath];
[database open];
searchResults = [[NSMutableArray alloc] initWithObjects:nil count:0];
NSString *query = [NSString stringWithFormat:#"select * from Locations where locationCode like '%#%%'", searchText];
FMResultSet *results = [database executeQuery:query];
while([results next]) {
locationCode *code = [[locationCode alloc] init];
code.code = [results stringForColumn:#"locationcode"];
code.subLocality= [results stringForColumn:#"sublocality"];
code.longitude= [results stringForColumn:#"longitude"];
code.latitude= [results stringForColumn:#"latitude"];
[searchResults addObject:code];
}
[database close];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
objectAtIndex:[self.searchDisplayController.searchBar
selectedScopeButtonIndex]]];
return YES;
}
#end
Try This it will work. paste the below code in cellforrowatindexpath method and don't forget to set your TableViewCell "Identifier" in your Attribute inspector
static NSString *CellIdentifier = #"Cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
I solved the problem by adding the tableview as an outlet. Then change the following line
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:#"vvv"];
to
CustomCell *cell = [customTableView dequeueReusableCellWithIdentifier:#"vvv"];

XCode error EXC_BAD_ACCESS when using sqlite3 + table + tab bar

I have a class ClsDatabase that is called to save / retrieve data.
There are also 2 views. The 2nd view have table that will display information based on what ClsDataBase retrieved. A tab-bar controls the 2 views.
It can load initially with the 1st view shown. However, when I select the 2nd view, it stops at main.m's
return UIApplicationMain(argc, argv, nil, NSStringFromClass([TestTabBarAppDelegate class]));
with error message: EXC_BAD_ACCESS.
I tried create another project but without ClsDatabase and just print some dummmy values in table, and it works. Not sure if its because of the class ClsDatabase
AppDelegate.m
#import "TestTabBarAppDelegate.h"
#import "TestTabBarFirstViewController.h"
#import "TestTabBarSecondViewController.h"
#implementation TestTabBarAppDelegate
#synthesize window = _window;
#synthesize tabBarController = _tabBarController;
- (void)dealloc
{
[_window release];
[_tabBarController release];
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
UIViewController *viewController1 = [[[TestTabBarFirstViewController alloc] initWithNibName:#"TestTabBarFirstViewController" bundle:nil] autorelease];
UIViewController *viewController2 = [[[TestTabBarSecondViewController alloc] initWithNibName:#"TestTabBarSecondViewController" bundle:nil] autorelease];
self.tabBarController = [[[UITabBarController alloc] init] autorelease];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
(2nd view).h
#import <UIKit/UIKit.h>
#import "ClsDatabase.h"
#interface TestTabBarSecondViewController : UIViewController<UIApplicationDelegate, UITabBarControllerDelegate>{
NSArray *arrDebtor;
ClsDatabase *dbDebtor;
}
#end
(2nd view.m)
#import "TestTabBarSecondViewController.h"
#implementation TestTabBarSecondViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Second", #"Second");
self.tabBarItem.image = [UIImage imageNamed:#"second"];
}
return self;
}
- (void)viewDidLoad
{
NSString *strSql;
dbDebtor = [[ClsDatabase alloc] initWithDbName:#"Debt"];
arrDebtor = [[NSArray alloc] init];
strSql = [NSString stringWithFormat:#"SELECT * FROM Debtor"];
arrDebtor = [dbDebtor ReturnQueryArray:strSql];
[super viewDidLoad];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if ([arrDebtor count] == 0) {
return 1;
}
else {
return [arrDebtor count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"Debtor";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if ([arrDebtor count] == 0) {
if (indexPath.row == 1) {
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
cell.textLabel.text = [NSString stringWithFormat:#"No tables or records found"];
return cell;
}
}
else {
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}
NSMutableDictionary *dictDebtor = [arrDebtor objectAtIndex:indexPath.row];
cell.textLabel.text = [dictDebtor valueForKey:#"Name"];
return cell;
}
}
You are doing lot's of things in code that should be done with IB and storyboarding.
Your logic in cellForRowAtIndexPath will fail on the first row, when indexPath.row is 0 and your arrDebtor is empty and your cell has not been created yet. That would explain the EXC_BAD_ACCESS error.

Resizing Cells in my project

I have this table with custom cells, how cal cells be resizable according to the content?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CustomTableCell";
static NSString *CellNib = #"DetailViewCell";
DetailViewCell *cell = (DetailViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellNib owner:self options:nil];
cell = (DetailViewCell *)[nib objectAtIndex:0];
}
cell.accessoryType = UITableViewCellAccessoryNone;
cell.cellTitleLabel.textColor = [UIColor blackColor];
cell.cellSubtitleLabel.textColor = [UIColor darkGrayColor];
informations = [[NSArray alloc] initWithObjects:titleString, subtitleString, stateString, categoryString, populationString, nil];
subtitles = [[NSArray alloc] initWithObjects:#"City", #"Country", #"State", #"Category", #"Population", nil];
cell.cellTitleLabel.text = [informations objectAtIndex:indexPath.row];
cell.cellSubtitleLabel.text = [subtitles objectAtIndex:indexPath.row];
return (DetailViewCell *) cell;
}
And here is the DetailViewCell.m
#import "DetailViewCell.h"
#implementation DetailViewCell
#synthesize cellTitleLabel;
#synthesize cellSubtitleLabel;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code.
}
return self;
}
- (void)dealloc {
[cellTitleLabel release];
[cellSubtitleLabel release];
[super dealloc];
}
Thanks!
After your cell content changed, reset cell height in - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath, and call [cell setNeedsDisplay]; to draw cell again.

Resources