IOS drop down with UITextField and UITableView - ios

I have created a drop down using UITextField and UITableView. When the user selects a textfield then a tableview is displayed as a drop down. I had set the tableview delegate and datasource in another class.
Now my issue is i wanted to get the text of the selected row in tableview on to the textfield i.e I want to send the tableview row text back to view controller(which consists of textfield) when user selects a row in tableview.
Thanks in advance.

add below code in In view did load of class in which you have added UITextField
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(addValueToTextField:) name:#"addValueToTextFiel" object:nil];
-(void)addValueToTextField:(NSNotification *) notification{
NSString* text = [notification text];
yourTextField.text = text;
}
And in Didselect delegate of UITable view of other class you have to add following code
UITableViewCell *selectedCell =[tableView cellForRowAtIndexPath:indexPath];
[[NSNotificationCenter defaultCenter] postNotificationName:#"addValueToTextField" object:nil userInfo:selectedCell.Text];
Or alternate of its is you can use custom delegates

Create custom delegate for controller with UITableView
ItemsList .h file
#protocol ItemsListDelegate : NSObject
#optional
- (void)itemSelected:(int)num withTitle:(NSString *)title;
#end
#interface ItemsList : UITableViewController{
id <ItemsListDelegate> delegate;
...
}
ItemsList .m file
#import "ItemsList.h"
#implementation ItemsList<UITableViewDataSource, UITableViewDelegate>
#synthesize delegate;
.....
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[delegate itemsSelected:[indexPath row] withTitle:[items objectAtIndex:[indexPath row]]];
}
.....
And in ViewController with your field set in .h
#import "ItemsList.h"
#interface ViewWithField<ItemsListDelegate>{
ItemsList *itemsList;
}
....
And in .m file
.....
- (void)viewDidLoad
{
itemList.delegate = self;
}
- (void)itemSelected:(int)num withTitle:(NSString *)title{
self.textField.text = title;
}
.....
Something like this. I don't check errors in this code. But look at this way.
Or use NotificationCenter, but this way is more correct.
Sorry for my ugly English.

Related

Access UIViewController methods from within subview

I subclassed UITableViewCell and initialized it in a UIView. From the TableView, I need to call a method in the parent ViewController (to perform segues, etc.).
Now, since the ViewController cannot be directly passed to its subviews (in respect of MVC principles), I created a delegation pattern, adding a protocol to the UITableView, and implementing the protocol as delegate in the UIVIewController.
The problem is that since the TableView is instantiated from the UIView, which is a subview of the Viewcontroller, I cannot assign the ViewController as delegate in the cellForRowAtIndexPath method since "self" would point to the View not the ViewController.
If I move all the table methods to the ViewController and instantiate the table from there, everything work as I wish. But that would not allow me to reuse the code in other ViewControllers.
CustomViewController.h
#import "CustomTableViewCell.h"
#interface CustomViewController : UIViewController<CustomTableViewCellDelegate>
CustomViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Create a sub-view where the custom table will appear
_customUIView = [[CustomUIView alloc] initWithFrame:CGRectMake(0, 60, self.view.frame.size.width, self.view.frame.size.height-60)];
[self.view addSubview:_customUIView];
[_customUIView populateTheView];
}
CustomUIView.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = [NSString stringWithFormat:#"cell%ld",(long)indexPath.row];
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
cell.delegate = self; // << THIS WILL NOT WORK AS IT WOULD POINT TO THE View, RATHER THAN THE ViewController
}
}
CustomTableViewCell.h
#protocol CustomTableViewCellDelegate <NSObject>
-(void)performSegue;
#end
#interface CustomTableViewCell : UITableViewCell
#property(weak, nonatomic) id<CustomTableViewCellDelegate>delegate;
#end
CustomTableViewCell.m
if ([self.delegate respondsToSelector:#selector(performSegue)]) {
[self.delegate performSegue];
}
The best solution I could find is using notifications.
In your viewController set up the observer in the viewWillAppear method. You will also need to remove it in the viewWillDisappear method or the app will crash:
// In the parent view controller
- (void)viewWillAppear:(BOOL)animated {
// Add observers to perform an action
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(imageTappedMessageReceived:) name:#"imageTapped" object:nil];
}
-(void) imageTappedMessageReceived:(NSNotification *)notification {
NSLog(#"The image was tapped");
}
- (void)viewWillDisappear:(BOOL)animated {
NSLog(#"View controller will disappear");
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"imageTapped" object:nil];
}
In your subview issue the notification when you need to (button pushed or other logic your have):
// In the subview
[[NSNotificationCenter defaultCenter] postNotificationName:#"imageTapped" object:self userInfo:tempDictionary];
The "imageTappedMessageReceived" method in the viewController will be fired every time the "imageTapped" notification is called in the subview.

In Split view controller: Call detailed view controller method from master view controller

In my MasterViewController uitabelview did select method change the DetailedViewController view.
My problem is when i change the view in DetailedViewController need to save the textfield values if user not saved manually.
How can i check this from MasterViewController or any idea to detect master view did select method called from DetailedViewController.
thanks in advance.
in your MasterViewController.h
#protocol CellSelectionDelegate <NSObject>
-(void)rowSelected:(NSIndexPath *)indexPath;
#end
#interface MasterViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
{
}
#property(nonatomic,strong)IBOutlet UITableView *menuTable;
#property (nonatomic, weak) id<CellSelectionDelegate> cellDelegate;
#end
in your MasterViewController.m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.cellDelegate respondsToSelector:#selector(rowSelected:)])
{
//sending selected indexPath, you can use indexPath.row in your detail view
[self.cellDelegate rowSelected:indexPath];
}
}
Now in your DetailedViewController.h
#import "MasterViewController.h"
#interface DetailedViewController : UIViewController<CellSelectionDelegate>
{
}
#property(nonatomic,strong)MasterViewController *masterView;
#end
in DetailedViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
//Set master page as the delegate.
masterView.delegate = self;
}
Now declare following delegate method
-(void)rowSelected:(NSIndexPath *)indexPath
{
NSLog(#"Your selected Row : %d",indexPath.row);
//do your work according to selection made in master view. use indexpath.row to identify which option was selected, you can also pass the other data with rowselected: method
}

Making Main View Controller Delegate of UITableViewDataSource

I'm new to iOS development. My Main View Controller doesn't display any cells from its table view. I was trying to set it up to display just one cell for now. The main view controller is a subclass of the UIViewController, and has a table view with the prototype cell as well. So my MainViewController.h file looks like below:
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController <UITableViewDataSource>
#property (weak, nonatomic) IBOutlet UIBarButtonItem *sidebarButton;
#end
I made the MainVewController a delegate of the UITableViewDataSource, is that the right idea here? My MainViewController.m looks like below:
#import "MainViewController.h"
#import "SWRevealViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Home";
SWRevealViewController *revealViewController = self.revealViewController;
if(revealViewController) {
[self.sidebarButton setTarget: self.revealViewController];
[self.sidebarButton setAction: #selector(revealToggle:)];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1; //change to number of post objects in array (array.count)
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"basicCell" forIndexPath:indexPath];
return cell;
}
#end
I don't understand what I'm doing wrong here. Shouldn't my MainViewController's Table View be properly displaying the cell? Thoughts?
You should use in viewDidLoad:
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
I don't see the Table View outlet. Did you forget to connect the Table View from interface builder to your view controller header file? After doing that you should also assign the delegate and data source properties of the table view to "self".
Your class just conforms to <UITableViewDataSource>
you should also conform UITableViewDelegate do it this way.
#interface MainViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
You missed setting the delegate and dataSource
It can be done in 2 ways:
using code:
[self.tableView setDelegate:self];
[self.tableView setDataSource:self];
put this code in viewDidLoad:
using storyboard: ctrl drag from tableView to your ViewController and set it as delegate and dataSource. see the Image below.
EDIT:
Why don't we need to connect the table's cell as well?
Ans: Table cell is returned from dataSource method tableView:cellForRowAtIndexPath:. This cell is displayed in the tableView. So we don't connect it in the storyboard. However we can configure it in the storyboard.
What's the difference between data source and delegate?
Ans: Delegate: The delegate is an object that is delegated control of the user interface for that event.
Datasource: A data source is like a delegate except that, instead of being delegated control of the user interface, it is delegated control of data.
For more information see Delegates and Data Sources and this answer.

Pass data from custom UITableViewCell and UIViewController

I am (fairly) familiar with segues and delegates to pass data between UIViewControllers, but my current situation is slightly different and I cannot get it working. Context: XCode 5 and iOS7 with Objective C.
I have a tableview (dynamic prototypes) that loads a custom cell (from a separate nib) that contains a UILabel and a UISwitch. CustomCell.xib loads its data from CustomCell.h/m. The main content is in ViewController.h/m and in that file I need to know whether the switch value changed (or actually the new value of the UISwitch). Obviously I know this within the CustomCell.h/m files but need to pass them to ViewController.h/m.
I tried using a delegate, but I cannot set a delegate for the UINib instance (in contrast to setting a delegate on a viewcontroller's instance). Also, the custom cell is implemented in the viewcontroller, so it is not pushed like another viewcontroller would be in a navigation stack.
CustomCell.h
#import <UIKit/UIKit.h>
#protocol CustomCellDelegate <NSObject>
- (void)switchControlValueChanged:(UISwitch*)switchControl toNewValue:(BOOL)value;
#end
#interface CustomCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *titleLabel;
#property (nonatomic, weak) IBOutlet UISwitch *switchControl;
#property (nonatomic, assign) id <CustomCellDelegate> delegate;
- (void)setValueForSwitchControlTo:(BOOL)value;
- (IBAction)changeColorForSwitchControl;
#end
CustomCell.m
- (void)changeColorForSwitchControl // value changed method
{
...
[self.delegate switchControlValueChanged:self.switchControl toNewValue:self.switchControl.on];
}
ViewController.h
#import <UIKit/UIKit.h>
#import "CustomCell.h"
#interface ViewController : UITableViewController <CustomCellDelegate>
...
#end
ViewController.m
- (void)viewDidLoad
{
...
// cannot set a delegate on the cellNib
UINib *cellNib = [UINib nibWithNibName:kCustomCell bundle:nil];
[self.tableView registerNib:cellNib forCellReuseIdentifier:kCustomCell];
}
- (void)switchControlValueChanged:(UISwitch *)switchControl toNewValue:(BOOL)value
{
NSLog(#"Switch changed!"); // this is not getting displayed
}
The right time to set your view controller to be the delegate of your cell would be when you set up other attributes of your cell. You do that in tableView:cellForRowAtIndexPath:.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kCustomCell forIndexPath:indexPath];
...
cell.delegate = self;
return cell;
}
Side note: registerNib:forCellReuseIdentifier: does exactly what it says, it just registers your nib for reuse. The contents of the nib aren't loaded until the table view decides to do that. It creates copies of the cell contained in the nib as and when required.
One option would be to use NSNotification, not as elegant but would work for your purpose. Every time the switch value changes, you can send a notification in CustomCell.m, something like:
NSDictionary *cellInfo = #{}; // add useful information to identify the cell to this dictionary
[[NSNotificationCenter defaultCenter] postNotificationName:#"SwitchValueChanged" object:nil userInfo:cellInfo];
Then you catch the notification in your ViewController by registering it as an observer with:
-(void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(yourMethod) name:#"SwitchValueChanged" object:nil];
}

Xcode - didSelectRowAtIndexPath doesn't run

i have this simple code in the didSelectRowAtIndexPath method:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath {
NSString *selected = #"test";
NSLog(#"You choose: %#", selected);
}
This is my ViewController.h:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> {
IBOutlet UITableView *tableData;
}
#end
When i run the App, the TableView display all data, but then i cliked in a cell the method above doesn't run (?)
Have you set the delegate for the tableview in your storyboard, select your table view right click and drag to the view controller and you should see the option to set dataSource delegate and tableviewdelegate - I forget the exact names.
e.g.: thats part of my code, but should show you what you need to do. You need to hand over the data somewhere.
NSDictionary *oneDict = [_noteBookArray objectAtIndex:indexPath.row];
NSString *touchString = [oneDict objectForKey:#"value"];
NSString *dateString = [oneDict objectForKey:#"timestamp"];
//call the method who does it
[_noteBookViewController setContentAndTimeStampWith:touchString and:dateString];
//set the present View Controller active (the controller who contains the values)
[self presentViewController:_noteBookViewController animated:YES completion:nil];
method from the notebookviewcontroller
- (void)setContentAndTimeStampWith:(NSString *)contentString and:(NSString *)timeStampString
{_textInputView.text = contentString;
_timeStampString = timeStampString;}
got it?

Resources