Resizing Cells in my project - xcode

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.

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.

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"];

Push Uiview and populate with data

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".

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.

How to solve slow scrolling in UITableView - using the YouTube API

I'm working with the google YouTube API, and I'm using this code found here http://pastebin.com/vmV2c0HT
The Code that slows things down is this one here
cell.imageView.image = [UIImage imageWithData:data];
When I remove that code it scrolls smoothly. Any idea on how I can go about having it load the images from google but still scroll smoothly? I've read some of the answers on loading images in a different way, but I still can't figure out how I'll make that work with the code I'm using.
Any help will be appreciated.
Bellow is the full code.
#import "RootViewController.h"
#interface RootViewController (PrivateMethods)
- (GDataServiceGoogleYouTube *)youTubeService;
#end
#implementation RootViewController
#synthesize feed;
- (void)viewDidLoad {
NSLog(#"loading");
GDataServiceGoogleYouTube *service = [self youTubeService];
NSString *uploadsID = kGDataYouTubeUserFeedIDUploads;
NSURL *feedURL = [GDataServiceGoogleYouTube youTubeURLForUserID:#"BmcCarmen"
userFeedID:uploadsID];
[service fetchFeedWithURL:feedURL
delegate:self
didFinishSelector:#selector(request:finishedWithFeed:error:)];
[super viewDidLoad];
}
- (void)request:(GDataServiceTicket *)ticket
finishedWithFeed:(GDataFeedBase *)aFeed
error:(NSError *)error {
self.feed = (GDataFeedYouTubeVideo *)aFeed;
[self.tableView reloadData];
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[feed entries] count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
GDataEntryBase *entry = [[feed entries] objectAtIndex:indexPath.row];
NSString *title = [[entry title] stringValue];
NSArray *thumbnails = [[(GDataEntryYouTubeVideo *)entry mediaGroup] mediaThumbnails];
cell.textLabel.text = title;
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[thumbnails objectAtIndex:0] URLString]]];
cell.imageView.image = [UIImage imageWithData:data];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 100.0f;
}
- (void)dealloc {
[super dealloc];
}
- (GDataServiceGoogleYouTube *)youTubeService {
static GDataServiceGoogleYouTube* _service = nil;
if (!_service) {
_service = [[GDataServiceGoogleYouTube alloc] init];
[_service setShouldCacheDatedData:YES];
[_service setServiceShouldFollowNextLinks:YES];
}
// fetch unauthenticated
[_service setUserCredentialsWithUsername:nil
password:nil];
return _service;
}
#end
GCD is a wonderful thing. Here is what I do:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"youTubeCell";
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell.
GDataEntryBase *entry = [[feed entries] objectAtIndex:indexPath.row];
NSString *title = [[entry title] stringValue];
NSArray *thumbnails = [[(GDataEntryYouTubeVideo *)entry mediaGroup] mediaThumbnails];
cell.textLabel.text = title;
// Load the image with an GCD block executed in another thread
dispatch_queue_t downloadQueue = dispatch_queue_create("image downloader", NULL);
dispatch_async(downloadQueue, ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[thumbnails objectAtIndex:0] URLString]]];
UIImage * image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = image;
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
[cell setNeedsLayout];
});
});
dispatch_release(downloadQueue);
return cell;
}
Scrolling is now super smooth. The only drawback is that when you scroll quickly, cells are re-used and sometimes the images change as new ones come in.

Resources