I'm not sure if I am approaching this the correct way so I need some help. I have a table with 5 rows for data to be entered. After the user enters all the data there is a button on the navigation bar that will add the data to the arrays. I want to set up another view controller that displays all of the data that has been entered by the user. I hope this makes sense. Here's what I have so far.
- (void)viewDidLoad
{
[super viewDidLoad];
[self initWithStyle: UITableViewStyleGrouped];
self.navigationController.navigationBarHidden=NO;
//self.navigationItem.hidesBackButton = YES;
// 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 = [[[UIBarButtonItem alloc] initWithTitle: #"Done" style:UIBarButtonItemStylePlain target: self action: #selector(add)] autorelease];
course = [[NSMutableArray alloc] init];
date = [[NSMutableArray alloc] init];
scores = [[NSMutableArray alloc] init];
rating = [[NSMutableArray alloc] init];
slope = [[NSMutableArray alloc] init];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
#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 5;
}
- (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];
cell.accessoryType = UITableViewCellAccessoryNone;
if ([indexPath section] == 0) {
if ([indexPath row] == 0) {
UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
playerTextField.adjustsFontSizeToFitWidth = YES;
playerTextField.textColor = [UIColor blackColor];
playerTextField.placeholder = #"Required";
playerTextField.keyboardType = UIKeyboardTypeDefault;
playerTextField.returnKeyType = UIReturnKeyNext;
playerTextField.text = [course objectAtIndex:indexPath.row];
playerTextField.backgroundColor = [UIColor whiteColor];
playerTextField.textAlignment = UITextAlignmentRight;
[playerTextField setEnabled: YES];
[cell addSubview:playerTextField];
[playerTextField release];
}
else if([indexPath row] == 1){
UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
playerTextField.adjustsFontSizeToFitWidth = YES;
playerTextField.textColor = [UIColor blackColor];
playerTextField.placeholder = #"Required";
playerTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
playerTextField.returnKeyType = UIReturnKeyDone;
playerTextField.text = [date objectAtIndex:indexPath.row];
playerTextField.backgroundColor = [UIColor whiteColor];
playerTextField.textAlignment = UITextAlignmentRight;
[playerTextField setEnabled: YES];
[cell addSubview:playerTextField];
[playerTextField release];
}
else if([indexPath row] == 2){
UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
playerTextField.adjustsFontSizeToFitWidth = YES;
playerTextField.textColor = [UIColor blackColor];
playerTextField.placeholder = #"Required";
playerTextField.keyboardType = UIKeyboardTypeNumberPad;
playerTextField.returnKeyType = UIReturnKeyDone;
playerTextField.text = [scores objectAtIndex:indexPath.row];
playerTextField.backgroundColor = [UIColor whiteColor];
playerTextField.textAlignment = UITextAlignmentRight;
[playerTextField setEnabled: YES];
[cell addSubview:playerTextField];
[playerTextField release];
}
else if([indexPath row] == 3){
UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
playerTextField.adjustsFontSizeToFitWidth = YES;
playerTextField.textColor = [UIColor blackColor];
playerTextField.placeholder = #"Required";
playerTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
playerTextField.returnKeyType = UIReturnKeyDone;
playerTextField.text = [rating objectAtIndex:indexPath.row];
playerTextField.backgroundColor = [UIColor whiteColor];
playerTextField.textAlignment = UITextAlignmentRight;
[playerTextField setEnabled: YES];
[cell addSubview:playerTextField];
[playerTextField release];
}
else if([indexPath row] == 4){
UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
playerTextField.adjustsFontSizeToFitWidth = YES;
playerTextField.textColor = [UIColor blackColor];
playerTextField.placeholder = #"Required";
playerTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
playerTextField.returnKeyType = UIReturnKeyDone;
playerTextField.text = [slope objectAtIndex:indexPath.row];
playerTextField.backgroundColor = [UIColor whiteColor];
playerTextField.textAlignment = UITextAlignmentRight;
[playerTextField setEnabled: YES];
[cell addSubview:playerTextField];
[playerTextField release];
}
}
}
if ([indexPath section] == 0) {
if ([indexPath row] == 0) {
cell.textLabel.text = #"Course";
}
else if([indexPath row] == 1){
cell.textLabel.text = #"Date";
}
else if([indexPath row] == 2){
cell.textLabel.text = #"Score";
}
else if([indexPath row] == 3){
cell.textLabel.text = #"Rating";
}
else if([indexPath row] == 4){
cell.textLabel.text = #"Slope";
}
}
return cell;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
[course replaceObjectAtIndex:textField.tag withObject:textField.text];
[date replaceObjectAtIndex:textField.tag withObject:textField.text];
[scores replaceObjectAtIndex:textField.tag withObject:textField.text];
[rating replaceObjectAtIndex:textField.tag withObject:textField.text];
[slope replaceObjectAtIndex:textField.tag withObject:textField.text];
return YES;
}
Wouldn't it just be easier to put 5 text fields in a view? I don't understand why you put them in a table view... If you want them to be scrollable, you can always just wrap your entire view in a scrollview, but I wouldn't do this with a table. As far as I know, it's generally bad to use a table view for input. It's more like a way to provide a user a display of some data, e.g. an array of objects. Also, usually, if you're using an NSMutableArray as a data source, you would also want your table data source methods like tableView:numberOfRowsInSection: to return a value based on the size of the array, rather than a magic, hard coded number.
I also see you're doing a lot of work in the code. You can have Interface Builder do all this stuff for you: just make a new UIViewController subclass with a xib that goes by the same name, design it in Interface Builder, and write the logic in the .m file.
For example, let's say I have a subclass of UIViewController called MyViewController, which has a view with 1 button 'next' and 2 UITextFields, conveniently called dateTF and scoreTF. My .h file would look something like this:
#import <UIKit/UIKit.h>
#interface MyViewController : UIViewController {
IBOutlet UITextField *dateTF;
IBOutlet UITextField *scoreTF;
}
#property (nonatomic, retain) UITextField *dateTF;
#property (nonatomic, retain) UITextField *scoreTF;
- (IBAction)clickedNext:(id)sender;
#end
Here we have a placeholder for the action that will be called when the "next" button is pressed, and 2 outlets to the text fields to retrieve the data from them. I don't need an IBOutlet to the button because I won't edit it.
The .m file could look like this:
#import "MyViewController.h"
#implementation MyViewController
#synthesize dateTF
#synthesize scoreTF;
// called when the button is clicked
- (IBAction)clickedNext:(id)sender{
NSString * date = self.dateTF.text;
NSString * score = self.scoreTF.text;
// do something with this data, like put up a model and go to the next view
}
#end
This assumes I have a xib file that contains my UI. In the xib you'll also need to make a few connections (easily done with ctrl+click_and_drag from source to target, e.g. from button to File's Owner): you'll need to connect the 2 IBOutlets and the button to call the IBAction, and you should be good to go.
Hope this helps!
I use data dictionary in passing data to a new viewController and uncomment the codes in the .m:
/*
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
}
return self;
}
*/
and add the new parameter in my case a dictionary:
Supposed the name is passDataHereController and selectedNews was declared as NSDictionary in the .h
// Note that I added the withDataDictionary:(NSDictionary*)passedDataDictionary
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil withDataDictionary:(NSDictionary*)passedDataDictionary{
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
// Custom initialization
self.selectedNews = passedDataDictionary;
}
return self;
}
Then in the controller where you are going to pass the data
//supposed dataTobePassed is already populated
passDataHereController *newView = [[passDataHereController alloc] initWithNibName:#"passDataHereController" bundle:nil withDataDictionary:dataTobePassed];
[self.navigationController pushViewController:newView animated:YES];
[newView release];
That's one way in passing data to another view, others may have simpler solutions.
Hope it helps.
Related
So, this is driving me nuts...
Everything works great, unless my datasource: an NSMutableArrray: _names contains more items than there are rows visible in the UITableView: namesTable.
then all hell breaks loose... cells are overlaying one another, there are empty cells, repeating cells.
here is my setup code.
#interface DetailViewController ()
{
NSMutableArray *_names;
}
My viewDidLoad method:
- (void) viewDidLoad
{
[super viewDidLoad];
self.navigationController.toolbar.barStyle = UIBarStyleBlackOpaque;
[[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleBlackOpaque];
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleBordered target:self action:#selector(handleBack:)];
self.navigationItem.leftBarButtonItem = backButton;
if (!_names)
_names = [[NSMutableArray alloc] init];
}
and cellForRowAtIndexPath:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellId = #"MyCustomCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
UITextField *nameTextField;
if (!cell || refreshCells)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellId];
self.view.bounds.origin.y+10,
self.view.bounds.size.width-19,
26.0)];*/
nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(self.view.bounds.origin.x+10,
self.view.bounds.origin.y+4,
self.view.bounds.size.width-19,
34.0)];
}
nameTextField.adjustsFontSizeToFitWidth = YES;
nameTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
nameTextField.backgroundColor = [UIColor clearColor];
nameTextField.autocorrectionType = UITextAutocorrectionTypeNo;
nameTextField.autocapitalizationType = UITextAutocapitalizationTypeWords;
nameTextField.textAlignment = UITextAlignmentLeft;
nameTextField.font = [UIFont fontWithName:#"Noteworthy-Bold" size:22.0];
nameTextField.keyboardType = UIKeyboardTypeDefault;
nameTextField.returnKeyType = UIReturnKeyDone;
nameTextField.clearButtonMode = UITextFieldViewModeNever;
nameTextField.delegate = self;
nameTextField.userInteractionEnabled = NO;
NSString *object = _names[indexPath.row];
nameTextField.text = [object description];
[cell.contentView addSubview:nameTextField];
cell.selectionStyle = UITableViewCellEditingStyleNone;
return cell;
}
can anybody, please tell show me what I am doing wrong?
You can use XIB to design your cell, instead of writing this much code. Also what is that refreshCells?? Also where are you adding data to your Array??
Better try to design the cell in XIB and IBOutlet it. Then load it in cellForRow...
In your code every time you are adding one textfield to your cell
[cell.contentView addSubview:nameTextField];
which is not necessary at all..
This could solve your problem.
I ended up subclassing UITableViewCell, and moving most of this code into:
#implementation DetailViewCustomCell
#synthesize nameTextField;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
nameTextField = [[UITextField alloc] init];
nameTextField.adjustsFontSizeToFitWidth = YES;
nameTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
nameTextField.backgroundColor = [UIColor clearColor];
nameTextField.autocapitalizationType = UITextAutocapitalizationTypeWords;
nameTextField.textAlignment = UITextAlignmentLeft;
nameTextField.font = [UIFont fontWithName:#"Noteworthy-Bold" size:22.0];
nameTextField.returnKeyType = UIReturnKeyDone;
nameTextField.userInteractionEnabled = NO;
[self.contentView addSubview:nameTextField];
self.selectionStyle = UITableViewCellEditingStyleNone;
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x+10;
CGFloat boundsY = contentRect.origin.x+4;
CGFloat boundsW = contentRect.size.width-19;
CGRect frame;
frame= CGRectMake(boundsX ,boundsY, boundsW, 34.0);
nameTextField.frame = frame;
}
and in my view controller:
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
DetailViewCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[DetailViewCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
NSString *object = _names[indexPath.row];
cell.nameTextField.text = [object description];
cell.nameTextField.delegate = self;
return cell;
}
this worked perfectly!
After a some time, searching here for some solutions we found this post:
How to navigate through textfields (Next / Done Buttons)
We tried that but unfortunately it doesn't work at all. Note that we put the UITextFields inside a UITableView.
We think the problem is around the Delegates but we don't know how to deal with it. Following i show you our code:
.h:
#import <UIKit/UIKit.h>
#interface LoginViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate> {
UITableView *loginTableView;
UITextField *textField;
}
#property UITableView *loginTableView;
#property UITextField *textField;
#property UIButton *loginButton;
#property UIButton *cancelButton;
#end
.m:
#import <QuartzCore/QuartzCore.h>
#import "LoginViewController.h"
#import "RootViewController.h"
#interface LoginViewController ()
#end
#implementation LoginViewController
#synthesize loginTableView, textField, loginButton, cancelButton;
- (void)viewDidLoad {
[super viewDidLoad];
// Make rounded corners view
[self.view.layer setCornerRadius:4.0];
[self.view.layer setMasksToBounds:YES];
self.view.layer.opaque = NO;
self.view.backgroundColor = [UIColor whiteColor];
// Create background image view
UIImageView *loginBackgroundImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height+20)];
// Create background's image
UIImage *backgroundImage = [UIImage imageNamed:#"loginbackground.png"];
loginBackgroundImageView.image = backgroundImage;
[self.view addSubview:loginBackgroundImageView];
// Create logo's image
UIImage *logoImage = [UIImage imageNamed:#"logo.png"];
// Create logo's image view
UIImageView *logoImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width/2 - logoImage.size.width/2, self.view.bounds.size.height/9, logoImage.size.width, logoImage.size.height)];
// Set image to logo's image view
logoImageView.image = logoImage;
[self.view addSubview:logoImageView];
// Create login table view
loginTableView = [[UITableView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width/2 - (self.view.bounds.size.width/1.2)/2, self.view.bounds.size.height/3, self.view.bounds.size.width/1.25, 100) style:UITableViewStylePlain
];
loginTableView.delegate = self;
loginTableView.dataSource = self;
// Create login container table view
UIImage *containerImage = [UIImage imageNamed:#"loginform.png"];
UIImageView *containerImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.bounds.size.width/2 - containerImage.size.width/2, self.view.bounds.size.height/3, containerImage.size.width, containerImage.size.height)];
containerImageView.image = containerImage;
[self.view addSubview:containerImageView];
// Custom table view
loginTableView.backgroundColor = [UIColor clearColor];
loginTableView.separatorColor = [UIColor clearColor];
// Disable scroll
loginTableView.scrollEnabled = NO;
// Add login table view to main view
[self.view addSubview:loginTableView];
// Create buttons images
UIImage *loginImage = [UIImage imageNamed:#"loginbtn2.png"];
UIImage *cancelImage = [UIImage imageNamed:#"cancelbtn.png"];
// Create buttons
loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
// Set buttons' normal state image
[loginButton setImage:loginImage forState:UIControlStateNormal];
[cancelButton setImage:cancelImage forState:UIControlStateNormal];
// Place buttons
loginButton.frame= CGRectMake((self.view.bounds.size.width/2)-(loginImage.size.width/2), self.view.bounds.size.height/1.65, loginImage.size.width, loginImage.size.height);
cancelButton.frame= CGRectMake((self.view.bounds.size.width/2)-(cancelImage.size.width/2), self.view.bounds.size.height/1.375, cancelImage.size.width, cancelImage.size.height);
// Set buttons' action
[loginButton addTarget:self action:#selector(loginButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cancelButton addTarget:self action:#selector(cancelButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
// Set button to the main view
[self.view addSubview:loginButton];
[self.view addSubview:cancelButton];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if ([indexPath section] == 0) {
textField = [[UITextField alloc] initWithFrame:CGRectMake(50, 11, 200, 25)];
textField.adjustsFontSizeToFitWidth = NO;
textField.textColor = [UIColor darkGrayColor];
textField.backgroundColor = [UIColor clearColor];
if ([indexPath row] == 0) {
textField.placeholder = #"Username";
textField.keyboardType = UIKeyboardTypeEmailAddress;
textField.returnKeyType = UIReturnKeyNext;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.tag = 0;
}
else {
textField.placeholder = #"Password";
textField.keyboardType = UIKeyboardTypeEmailAddress;
textField.returnKeyType = UIReturnKeyDone;
textField.autocorrectionType = UITextAutocorrectionTypeNo;
textField.autocapitalizationType = UITextAutocapitalizationTypeNone;
textField.secureTextEntry = YES;
textField.tag = 1;
}
textField.clearButtonMode = UITextFieldViewModeAlways;
textField.delegate = self;
[textField setEnabled: YES];
[cell addSubview:textField];
}
}
if ([indexPath section] == 0) { // Email & Password Section
if ([indexPath row] == 0) { // Email
cell.imageView.image = [UIImage imageNamed:#"usernameico.png"];
}
else {
cell.imageView.image = [UIImage imageNamed:#"passwordico.png"];
}
}
else { // Login button section
cell.textLabel.text = #"Log in";
}
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *) tableView {
return 1;
}
-(BOOL)textFieldShouldReturn:(UITextField*) formTextField {
NSInteger nextTag = formTextField.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[formTextField resignFirstResponder];
}
return NO; // We do not want UITextField to insert line-breaks.
}
- (void)loginButtonPressed: (UIButton *) sender {
}
- (void)cancelButtonPressed: (UIButton *) sender {
}
#end
Thank you in advance!
The problem is the table. When you ask you text view for it's superview, it will return the cell, which doesn't contain any other siblings. Try:
UIResponder* nextResponder = [tableView viewWithTag:nextTag];
Creare an array with your UITextField inside the cellForRowAtIndexPath: method..
[txtArray addObject:textField];
and then this bellow method it will work...
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
int i=[txtArray count];
int x=textField.tag+1;
UITextField *nextTextField = (UITextField *)[txtArray objectAtIndex:x];
if (x<i-1) {
[nextTextField becomeFirstResponder];
} else {
[textField resignFirstResponder];
}
return YES;
}
i hope this help you...
Give tag to your textField one by one and use textField delegate
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
int NextTextField = textField.tag+1;
UITextField *txt = (UITextField *) [tableView viewWithTag:NextTextField];
[txt becomeFirstResponder];
return NO;
}
I've wired a UISearchDisplayController into my app along with a search bar. I've initialized it as so:
self.filteredObjectArray = [NSMutableArray arrayWithCapacity:[self.objectArray count]];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 43)];
searchBar.delegate = self;
[self.view addSubview:searchBar];
UISearchDisplayController *searchDisplay = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
searchDisplay.delegate = self;
searchDisplay.searchResultsTableView.delegate = self;
searchDisplay.searchResultsDataSource = self;
searchDisplay.searchResultsDelegate = self;
Which is pretty much the way I've seen it in other examples. I've also implemented the appropriate delegate methods, with the important filterContentForSearchText and the shouldReload* methods shown below:
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
[self.filteredObjectArray removeAllObjects]; // First clear the filtered array.
for (XRay *xray in objectArray) {
NSString *combinedLabel = [self combinedLabel:xray];
if ([combinedLabel rangeOfString:searchText options:(NSCaseInsensitiveSearch)].location != NSNotFound) {
[self.filteredObjectArray addObject:xray];
}
}
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
[self filterContentForSearchText:self.searchDisplayController.searchBar.text scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
return YES;
}
However my search is not working when I give the search text box focus or input any characters. You'll also notice that the greyed out view does not appear over my regular table view.
EDIT
cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"XraySearchChoice";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
XRay *xray = nil;
if (tableView == self.searchDisplayController.searchResultsTableView) {
xray = [self.filteredObjectArray objectAtIndex:indexPath.row];
} else {
xray = [self.objectArray objectAtIndex:indexPath.row];
}
cell.textLabel.text = [self combinedLabel:xray];
return cell;
}
I figured out what was wrong and I'm a bit surprised to be honest. Once I set a property on the SearchTableViewController:
#property (nonatomic, strong) UISearchDisplayController *searchDisplay;
And updated my code to use that one, everything worked from there. Here is my initializing code with the new property.
- (void)viewDidLoad
{
self.filteredObjectArray = [NSMutableArray arrayWithCapacity:[self.objectArray count]];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 43)];
searchBar.delegate = self;
self.tableView.tableHeaderView = searchBar;
self.searchDisplay = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchDisplay.delegate = self;
self.searchDisplay.searchResultsDataSource = self;
self.searchDisplay.searchResultsDelegate = self;
}
Try with below code it will help you
self.filteredObjectArray = [NSMutableArray arrayWithCapacity:[self.objectArray count]];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 43)];
searchBar.delegate = self;
//[self.view addSubview:searchBar];
self.theTableView.tableHeaderView = searchBar;//theTableView your tableview object
UISearchDisplayController *searchDisplay = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
self.searchController = searchDisplay;
[searchBar release];
searchDisplay.delegate = self;
searchDisplay.searchResultsDataSource = self;
searchDisplay.searchResultsDelegate = self;
I have a custom UITableViewCell as such:
#implementation CellWithThreeSubtitles
#synthesize title, subTitle1, subTitle2, subTitle3;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
self.textLabel.backgroundColor = self.backgroundColor;
self.textLabel.opaque = NO;
self.textLabel.textColor = [UIColor blackColor];
self.textLabel.highlightedTextColor = [UIColor whiteColor];
self.textLabel.font = [UIFont boldSystemFontOfSize:22.0];
}
return self;
}
- (void)layoutSubviews
{
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGRect frame = CGRectMake(35.0, 0, contentRect.size.width, 50.0);
self.textLabel.frame = frame;
UILabel *subLabel1 = [[UILabel alloc] init];
frame = CGRectMake(35.0, 34.0, contentRect.size.width, 25.0);
subLabel1.font = [UIFont systemFontOfSize:18.0];
subLabel1.backgroundColor = [UIColor clearColor];
subLabel1.text = subTitle1;
subLabel1.opaque = NO;
subLabel1.frame = frame;
[self.contentView addSubview:subLabel1];
UILabel *subLabel2 = [[UILabel alloc] init];
frame = CGRectMake(35.0, 54.0, contentRect.size.width, 25.0);
subLabel2.font = [UIFont boldSystemFontOfSize:18.0];
subLabel2.backgroundColor = [UIColor clearColor];
subLabel2.text = subTitle2;
subLabel2.opaque = NO;
subLabel2.frame = frame;
[self.contentView addSubview:subLabel2];
UILabel *subLabel3 = [[UILabel alloc] init];
frame = CGRectMake(contentRect.size.width-100.0, 54.0, contentRect.size.width, 25.0);
subLabel3.font = [UIFont systemFontOfSize:18.0];
subLabel3.backgroundColor = [UIColor clearColor];
subLabel3.text = subTitle3;
subLabel3.opaque = NO;
subLabel3.frame = frame;
[self.contentView addSubview:subLabel3];
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)dealloc {
[super dealloc];
[subTitle4 release];
[subTitle3 release];
[subTitle2 release];
[subTitle1 release];
[title release];
}
When I implement it in my UITableView like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
int section = [indexPath indexAtPosition:0];
static NSString *kCustomCellID = #"AppointmentCellID";
CellWithThreeSubtitles *cell = (CellWithThreeSubtitles *)[tableView dequeueReusableCellWithIdentifier:kCustomCellID];
if (cell == nil) {
cell = (CellWithThreeSubtitles *)[[[CellWithThreeSubtitles alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kCustomCellID] autorelease];
}
switch (section) {
case 0:
if ([wineArray count]==0) {
cell.textLabel.text = #"No wine favorites selected yet";
}else{
cell.subTitle1 = [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Varietal"];
cell.subTitle2 = [NSString stringWithFormat:#"Bin No. %#", [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Bin"]];
cell.subTitle3 = [NSString stringWithFormat:#"$%#", [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Price"]];
cell.textLabel.text = [NSString stringWithFormat:#"%# (%#)", [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Name"], [[wineArray objectAtIndex:indexPath.row] objectForKey:#"Availability"]];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.userInteractionEnabled = NO;
break;
case 1:
if ([dinnerArray count]==0)
cell.textLabel.text = #"No dinner favorites selected yet";
else
cell.textLabel.text = [NSString stringWithFormat:#"%#", [[dinnerArray objectAtIndex:indexPath.row] objectForKey:#"Name"]];
break;
}
return cell;
}
the contents of the cell duplicates on top of itself every time the orientation of the device changes. Is it redrawing the cell every time the device rotates? And if so, How can I keep it from doing so?
You should be creating the subviews and adding them to your cell's subviews array in your -initWithStyle:reuseIdentifier: method. You only need to create the subviews once. The -layoutSubviews method is invoked repeatedly by the framework whenever the device orientation changes, to allow you to resize and/or move the subviews (plus make any other minor adjustments) to compensate for differences between the orientations.
I suspect layoutSubViews is being called on rotation, and re-drawing new labels on top of your old ones. If you remove any labels from the table cell at the beginning of layoutSubViews that would probably fix that issue, or you could create them in the init and then just position them in layoutSubViews.
I am getting memory leak at text fiels please suggest me how to resolve it.
I written the code in init() as:
eventTextField = nil;
eventTextField = [[UITextField alloc]initWithFrame:CGRectMake(10, 15, 300, 50)];
eventTextField.placeholder = #"Event Name";
[eventTextField setFont:[UIFont boldSystemFontOfSize:14]];
eventTextField.returnKeyType = UIReturnKeyDone;
eventTextField.keyboardAppearance = UIKeyboardAppearanceDefault;//Showing leak at this line
eventTextField.keyboardType = UIKeyboardTypeDefault;
eventTextField.delegate=self;
and I released it in dealloc method.
and in cellForRowIndex I am adding it as subview.
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MasterViewIdentifier"];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"MasterViewIdentifier"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIView* elementView = [[UIView alloc] initWithFrame:CGRectMake(20,170,320,280)];
elementView.tag = 0;
elementView.backgroundColor=[UIColor clearColor];
[cell.contentView addSubview:elementView];
[elementView release];
}
UIView* elementView = [cell.contentView viewWithTag:0];
elementView.backgroundColor=[UIColor clearColor];
for(UIView* subView in elementView.subviews)
{
[subView removeFromSuperview];
}
if(indexPath.section == 0 && indexPath.row == 0)
{
CorkItAppDelegate* appDelegate = (CorkItAppDelegate*)[[UIApplication sharedApplication] delegate];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
wineNameTitleLabel.numberOfLines = 0;
[wineNameTitleLabel setFont:[UIFont boldSystemFontOfSize:14]];
if(appDelegate.isNewWine == YES)
{
wineNameTitleLabel.textColor = [UIColor blackColor] ;
wineNameTitleLabel.text = appDelegate.getNewWineName;
}
else
{
if([event.eventWineName length]>0)
{
wineNameTitleLabel.textColor = [UIColor blackColor] ;
wineNameTitleLabel.text = event.eventWineName;
}
else
{
wineNameTitleLabel.text = #"Wine Name";
}
}
[elementView addSubview:wineNameTitleLabel];
}
else if(indexPath.section == 1)
{
if(isRightButton == YES)
{
eventTextField.enabled = NO;
}
else
{
eventTextField.enabled = YES;
}
if([event.eventName length] > 0)
{
eventTextField.text = event.eventName;
}
else
{
eventTextField.text = #"";
}
[elementView addSubview:eventTextField];
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
Hope I get wucik response from your side.
Thanks in advance,
Monish.
If you still need the eventTextField. You should create a property and instance variable for it. So that, you can your class own the eventTextField and release it in the dealloc. Like this:
#interface A {
UITextField *eventTextField;
}
#property (nonatomic, retain) UITextField *eventTextField;
#end
#implementation A
#synthesize eventTextField;
- (id)init {
eventTextField = [[UITextField alloc]init];
}
- (void)dealloc {
[eventTextField release];
}
#end
you should release the UITextField after adding it to the subview
[foo addSubview:eventTextField];
[eventTextField release];
eventTextField = nil; is unnecessary btw as eventTextField is a ivar is already zeroed (pointer set to 0x0(nil))