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;
Related
I am a beginner to iOS development and am having trouble finding the cause for this issue.
I have a simple app with a Master and DetailView controllers. The Master View contains an UITableView with a SearchController. Selecting any row on the UITableView will transition to the detailview.
The app freezes when I perform the following sequence
Launch app
Pull down the search bar
Enter text
Select a row from the search results
Select back from the detail view
Now the app freezes after the ViewDidLoad method of the MasterView is loaded. I can't find anything in the system.log.
Here's the code from the MasterViewController
- (void)viewWillAppear:(BOOL)animated {
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)];
[self.tableView setContentOffset:CGPointMake(0,40)];
self.tableView.tableHeaderView = self.searchBar;
// Create and configure the search controller
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *months = #"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec";
feeds = [months componentsSeparatedByString:#","];
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"numberOfRowsInSection");
if(tableView == self.tableView)
{
return feeds.count;
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF like %#", self.searchBar.text];
self.filteredFeeds = [feeds filteredArrayUsingPredicate:predicate];
return feeds.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
cell.textLabel.text = [feeds objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
NSDate *object = _objects[indexPath.row];
self.detailViewController.detailItem = object;
}
[self performSegueWithIdentifier: #"showDetail" sender: self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDate *object = _objects[indexPath.row];
[[segue destinationViewController] setDetailItem:object];
}
}
I have uploaded the entire project at the location below.
https://www.dropbox.com/s/yok9vngzv143npa/search.zip
Any kind of assistance is appreciated.
I can not able to run your program because version issue of iOS.
But i seen your code. I suspect on 1 point on following code,
- (void)viewWillAppear:(BOOL)animated {
self.searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 44.0f)];
[self.tableView setContentOffset:CGPointMake(0,40)];
self.tableView.tableHeaderView = self.searchBar;
// Create and configure the search controller
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
}
You create/allocate UISearchBar and UISearchDisplayController again and again while you get back from DetailViewController to MasterViewController, these may be cause of your app freezing.
"viewWillAppear" called before the receiver’s view is about to be added to a view hierarchy and before any animations are configured for showing the view.
"viewDidLoad" called after view controller has loaded its view hierarchy into memory.
I suggest you place your one time allocations view code in viewDidLoad method.
For more information go through this doc https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/instm/UIViewController/viewDidLoad
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!
I made a custom UIAlertView, who look like this
http://www.odlgs.com/customAlertBefore.jpg
The problem is that when I rotate to another interface orientation the alert change it's size and looks like this:
http://www.odlgs.com/customAlertAfter.jpg
I made a NSNotification that allows me to resize controls when I switch to another interface orientation, but doesn't work with my UIAlertView, and the autoresizingMask property do not works too, anyone that have experience the same problem or has some idea? here is the code:
/*** THIS IS THE CLASS OF MY CUSTOM ALERTVIEW ***/
#import "AlertTableViewController.h"
#import "Theme.h"
#implementation AlertTableViewController
#synthesize textField, caller, context, data;
-(id)initWithCaller:(id)_caller data:(NSArray*)_data title:(NSString*)_title andContext:(id)_context{
NSMutableString *messageString = [NSMutableString stringWithString:#"\n"];
tableHeight = 0;
if([_data count] != 0){
for(int i = 0; i < [_data count]; i++){
//[messageString appendString:#"\n\n"];
//tableHeight += 53;
tableHeight = 150;
}
}else{
//messageString = #"\n\n\n\n\n\n\n\n\n\n";
tableHeight = 207;
}
if(self = [super initWithTitle:_title message:messageString delegate:self cancelButtonTitle:nil otherButtonTitles:nil]){
self.caller = _caller;
self.context = _context;
self.data = _data;
[self prepare];
}
return self;
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
[self.caller didSelectRowAtIndex:-1 withContext:self.context];
}
-(void)show{
self.hidden = YES;
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:#selector(myTimer:) userInfo:nil repeats:NO];
[super show];
}
-(void)myTimer:(NSTimer*)_timer{
self.hidden = NO;
[myTableView flashScrollIndicators];
}
//HERE I ADD THE CONTROLS TO MY CUSTOM ALERTVIEW
-(void)prepare{
self.autoresizingMask = UIViewAutoresizingFlexibleHeight;
textField = [[UITextField alloc] initWithFrame:CGRectMake(11, 50, 261, 30)];
textField.backgroundColor = [UIColor whiteColor];
textField.delegate = self;
myTableView = [[UITableView alloc] initWithFrame:CGRectMake(11, 115, 261, tableHeight) style:UITableViewStylePlain];
myTableView.scrollEnabled = NO;
myTableView.delegate = self;
myTableView.dataSource = self;
UILabel *sourcesTitle = [[UILabel alloc] initWithFrame:CGRectMake(11, 90, 261, 20)];
sourcesTitle.text = #"Source";
sourcesTitle.textColor = [UIColor whiteColor];
sourcesTitle.backgroundColor = [UIColor clearColor];
sourcesTitle.font = [UIFont fontWithName:kLKTtFONT_NAME size:kLKTtFONT_LABEL_SIZE_17];
UIButton *ok = [UIButton buttonWithType:UIButtonTypeRoundedRect];
ok.frame = CGRectMake(11, 280, 120, 30);
[ok setTitle:#"Ok" forState:UIControlStateNormal];
[ok addTarget:self action:#selector(saveNetwork) forControlEvents:UIControlEventTouchDown];
UIButton *cancel = [UIButton buttonWithType:UIButtonTypeRoundedRect];
cancel.frame = CGRectMake(150, 280, 120, 30);
[cancel setTitle:#"Cancel" forState:UIControlStateNormal];
[cancel addTarget:self action:#selector(cancel) forControlEvents:UIControlEventTouchDown];
[self addSubview:sourcesTitle];
[self addSubview:ok];
[self addSubview:cancel];
[self addSubview:myTableView];
[self addSubview:textField];
[textField becomeFirstResponder];
UIImageView *imgView = [[[UIImageView alloc] initWithFrame:CGRectMake(11, 50, 261, 4)] autorelease];
imgView.image = [UIImage imageNamed:#"top.png"];
[self addSubview:imgView];
imgView = [[[UIImageView alloc] initWithFrame:CGRectMake(11, tableHeight+46, 261, 4)] autorelease];
imgView.image = [UIImage imageNamed:#"bottom.png"];
[self addSubview:imgView];
CGAffineTransform myTransform = CGAffineTransformMakeTranslation(0.0, 10);
[self setTransform:myTransform];
}
-(void)saveNetwork{
CreateNetworkCommunication *communication = [[CreateNetworkCommunication alloc] init];
communication.sourceId = [[[data objectAtIndex:selectedSource] valueForKey:#"Id"] integerValue];
communication.name = textField.text;
communication.delegate = self;
[communication doRequest];
}
-(void)finishSaveNetworkRequestWithResponse:(OwnerResult*)response{
if (response.StatusCode == 0) {
[super dismissWithClickedButtonIndex:0 animated:YES];
[self.caller refreshNetworks];
}
else {
UIAlertView *error = [[UIAlertView alloc] initWithTitle:self.title message:NSLocalizedString(#"alert.error-saving", nil) delegate:nil cancelButtonTitle:NSLocalizedString(#"OK", nil) otherButtonTitles: nil];
[error show];
[error release];
}
}
-(void)cancel{
[super dismissWithClickedButtonIndex:1 animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = (UITableViewCell*) [tableView dequeueReusableCellWithIdentifier:#"ABC"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:#"ABC"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.font = [UIFont boldSystemFontOfSize:14];
}
if (selectedSource != indexPath.row)
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.text = [[data objectAtIndex:indexPath.row] valueForKey:#"Name"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//[self dismissWithClickedButtonIndex:0 animated:YES];
//[self.caller didSelectRowAtIndex:indexPath.row withContext:self.context];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
selectedSource = indexPath.row;
[tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
selectedSource = indexPath.row;
cell.accessoryType = UITableViewCellAccessoryNone;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [data count];
}
-(void)dealloc{
self.data = nil;
self.caller = nil;
self.context = nil;
[myTableView release];
[super dealloc];
}
/*** THIS IS THE VIEWCONTROLLER WHERE I IMPLEMENT THE CUSTOM ALERTVIEW ***/
#import "NetworkSelectorViewController.h"
#interface NetworkSelectorViewController ()
#end
#implementation NetworkSelectorViewController
#synthesize delegate, alert;
-(void)add {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(resizeTaxonomyView:) name:#"resizeTaxonomyView" object:nil];
alert = [[AlertTableViewController alloc] initWithCaller:self data:sources title:#"New Network" andContext:nil];
//UIAlertView * alert = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:#"%# %#", NSLocalizedString(#"button.new", nil), self.title] message:#"" delegate:self cancelButtonTitle:NSLocalizedString(#"button.cancel", nil) otherButtonTitles:NSLocalizedString(#"button.save", nil), nil];
//alert.alertViewStyle = UIAlertViewStylePlainTextInput;
//UITextField * alertTextField = [alert textFieldAtIndex:0];
//UITableView *tableView = [[UITableView alloc] initWithFrame:CGRectMake(11, 110, 261, 200) style:UITableViewStylePlain];
//UIButton* okButton = [[UIButton alloc] initWithFrame:CGRectMake(11, 30, 50, 50)];
//[alert addSubview:okButton];
//okButton.frame = CGRectMake(okButton.frame.origin.x, 400, okButton.frame.size.width, okButton.frame.size.height);
//alertTextField.keyboardType = UIKeyboardTypeAlphabet;
//alertTextField.placeholder = self.title;
//[alert addSubview:tableView];
//alert.data = [[NSArray alloc] initWithObjects:#"1",#"2", nil];
alert.delegate = self;
NSLog(#"ALERT SUBVIEWS: %#", alert.subviews);
[alert show];
alert.frame = CGRectMake(alert.frame.origin.x, alert.frame.origin.y, alert.frame.size.width, 370);
NSLog(#"X:%f Y:%f W:%f H:%f", alert.frame.origin.x, alert.frame.origin.y, alert.frame.size.width, alert.frame.size.height);
UIButton* button1 = (UIButton*)[alert.subviews objectAtIndex:2];
button1.frame = CGRectMake(0,300, 50, button1.frame.size.height);
//[alert release];
}
- (void)resizeTaxonomyView:(NSNotification *)notification {
// El mÈtodo recibe un objeto de tipo NSNotification cuya propiedad object
// alberga el objeto pasado como parametro. En este caso hacemos un casting
// del objeto a NSString.
if(UIInterfaceOrientationIsLandscape(self.interfaceOrientation))
alert.frame = CGRectMake(alert.frame.origin.x, alert.frame.origin.y, alert.frame.size.width, 500);
else
alert.frame = CGRectMake(alert.frame.origin.x, alert.frame.origin.y, 500, 1000);
}
The NSnotification works, the method triggers, but the alertview doesnt autoresize
uialertviewcustom
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.
I am quite new to IOS development, so forgive me if this problem turns out to be trivial. The following is the case:
I want to be able to call the didSelectRowAtIndexPath method to trigger some action when a user interacts with a table view cell. However, it seems that this method is never called for some reason. I am fairly certain that my code is valid. I set the delegate and dataSource properties and I conform to the UITableViewDelegate and UITableViewDataSource protocols.
If someone could shed some light on this, I would be very grateful.
My code:
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#class Employee;
#define kTelephoneRowIndex 0
#define kEmailRowIndex 1
#define kLeftLabelTag 4096
#define kRightLabelTag 4097
#interface PersonnelDetailsViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource, MFMailComposeViewControllerDelegate> {
UITableView *contactDetailsTable;
Employee *employee;
}
#property (nonatomic, retain) UITableView *contactDetailsTable;
#property (nonatomic, retain) Employee *employee;
+ (NSString *)resourceFilePath:(NSString *)fileName ofType:(NSString *)type;
#end
and my .m file
#import <QuartzCore/QuartzCore.h>
#import "PersonnelDetailsViewController.h"
#import "Employee.h"
#implementation PersonnelDetailsViewController
#synthesize contactDetailsTable, employee;
+ (NSString *)resourceFilePath:(NSString *)fileName ofType:(NSString *)type {
return [[NSBundle mainBundle] pathForResource:fileName ofType:type];
}
- (void)loadView {
[super loadView];
// Create the header view for the table view
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 110)];
// Set the image, using rounded corners
UIImage *employeeImage;
if ([employee.image length] == 0)
employeeImage = [UIImage imageNamed:#"logoL1nda70by80"];
else
employeeImage = [UIImage imageNamed:employee.image];
UIImageView *employeeImageView = [[UIImageView alloc] initWithImage:employeeImage];
employeeImageView.frame = CGRectMake(10, 15, 70, 80);
employeeImageView.layer.masksToBounds = YES;
employeeImageView.layer.cornerRadius = 5.0;
employeeImageView.layer.borderWidth = 1.0;
employeeImageView.layer.borderColor = [[UIColor grayColor] CGColor];
[headerView addSubview:employeeImageView];
UILabel *nameView = [[UILabel alloc] initWithFrame:CGRectMake(95, 35, 180, 20)];
nameView.text = employee.name;
nameView.font = [UIFont boldSystemFontOfSize:18];
[headerView addSubview:nameView];
UILabel *functionView = [[UILabel alloc] initWithFrame:CGRectMake(95, 55, 140, 16)];
functionView.text = employee.function;
functionView.textColor = [UIColor grayColor];
functionView.font = [UIFont systemFontOfSize:14];
[headerView addSubview:functionView];
[employeeImage release];
[employeeImageView release];
[nameView release];
[functionView release];
contactDetailsTable = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 370) style: UITableViewStyleGrouped];
contactDetailsTable.backgroundColor = [UIColor clearColor];
contactDetailsTable.tableHeaderView = headerView;
[headerView release];
contactDetailsTable.delegate = self;
contactDetailsTable.dataSource = self;
[self.view addSubview:contactDetailsTable];
}
- (void)viewDidUnload {
self.contactDetailsTable = nil;
self.employee = nil;
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
[contactDetailsTable reloadData];
}
- (void)dealloc {
[contactDetailsTable release];
[employee release];
[super dealloc];
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;did
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *contactDetailIdentifier = #"contactDetailIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:contactDetailIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:contactDetailIdentifier] autorelease];
UILabel *leftLabel = [[UITextField alloc] initWithFrame:CGRectMake(5, 12, 70, 25)];
leftLabel.textAlignment = UITextAlignmentRight;
leftLabel.textColor = [UIColor grayColor];
leftLabel.tag = kLeftLabelTag;
leftLabel.userInteractionEnabled = NO;
[cell.contentView addSubview:leftLabel];
[leftLabel release];
UILabel *rightLabel = [[UITextField alloc] initWithFrame:CGRectMake(90, 12, 160, 25)];
rightLabel.font = [UIFont boldSystemFontOfSize:16];
rightLabel.tag = kRightLabelTag;
rightLabel.userInteractionEnabled = NO;
[cell.contentView addSubview:rightLabel];
[rightLabel release];
}
NSUInteger row = [indexPath row];
UILabel *leftLabel = (UILabel *)[cell viewWithTag:kLeftLabelTag];
UILabel *rightLabel = (UILabel *)[cell viewWithTag:kRightLabelTag];
switch (row) {
case kTelephoneRowIndex:
leftLabel.text = #"telefoon";
rightLabel.text = employee.phone;
break;
case kEmailRowIndex:
leftLabel.text = #"e-mail";
rightLabel.text = employee.email;
break;
default:
break;
}
return cell;
}
#pragma mark -
#pragma mark Table View Delegate Methods
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
return nil;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = indexPath.row;
if (row == 1) {
MFMailComposeViewController *mailController = [[MFMailComposeViewController alloc] init];
[mailController setToRecipients:[NSArray arrayWithObject:employee.email]];
[mailController.navigationBar setTintColor:[UIColor blackColor]];
[self presentModalViewController:mailController animated:YES];
mailController.mailComposeDelegate = self;
[mailController release];
}
NSLog(#"Row selected is: %d", row);
}
#pragma mark -
#pragma mark MFMailCompose View Delegate Methods
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
[self dismissModalViewControllerAnimated:YES];
}
#end
Check the doc for tableView:willSelectRowAtIndexPath::
Return an NSIndexPath object other than indexPath if you want another cell to be selected. Return nil if you don't want the row selected.
You are returning nil, basically saying the table view that you don't want that row selected. Therefore tableView:didSelectRowAtIndexPath: is not called.
When I had this problem I found the solution was to use willSelectRowAtIndexPath. In other places in the same project didSelectItemAtIndexPath is getting called fine.
#pragma mark - UITableViewDelegate
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// for some reason this is getting called instead of didSelectItemAtIndexPath
[self viewDetails:indexPath.row];
return indexPath;
}
- (void)tableView:(UITableView *)tableView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
// [self viewDetails:indexPath.row];
}