I am learning how to use storyboards by making a very simple app. On the main view controller (InfoViewController), I have a textField by the name: nameField. After entering text in this field, when I enter the save button, the text should should get appended to the array (list) (declared in TableViewController) and be displayed on the table in TableViewController.
Also, the segue identifier is: GoToTableViewController.
However, the text does not get passed from nameField to the list (array). At first, I assumed that I was making some mistake with the textField. So I replaced it with a static text. But that did not help either. Then I checked if the string has been added to the array by using NSLog() , but every time I get Null. From my understanding, the list (array) is not created until TableViewController is loaded. For that reason, I alloc and init list in InfoViewController. But it does not help.
Can somebody please help me find out the mistake that I am making?
Thanks!
Relevant sections of my code are as follows:
InfoViewController.h
#import <UIKit/UIKit.h>
#class TableViewController;
#interface InfoViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *nameField;
#property (strong, nonatomic) TableViewController *tableViewController;
#end
InfoViewController.m
#import "InfoViewController.h"
#import "TableViewController.h"
#implementation InfoViewController
#synthesize nameField;
#synthesize tableViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
tableViewController = [[TableViewController alloc] init];
tableViewController.list = [[NSMutableArray alloc] init];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqual:#"GoToTableViewController"])
{
/* Pass data to list and then reloadTable data */
tableViewController = segue.destinationViewController;
tableViewController.infoViewController = self;
// (*) [tableViewController.list addObject:nameField.text];
// (*) [tableViewController.list addObject:#"Hi!"];
[tableViewController.list insertObject:#"Hi" atIndex:0];
// (**) NSLog(#"%#", [tableViewController.list objectAtIndex:0]);
[tableViewController.tableView reloadData];
}
}
#end
( * ) I inserted these statements to see if I was making a mistake with using the value in nameField.
( ** ) This statement is meant to check the value inserted in the array.
TableViewController.h
#import <UIKit/UIKit.h>
#class InfoViewController;
#interface TableViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *list;
#property (strong, nonatomic) InfoViewController *infoViewController;
#end
TableViewController.m
#import "TableViewController.h"
#import "InfoViewController.h"
#implementation TableViewController
#synthesize list;
#synthesize infoViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
list = [[NSMutableArray alloc] init];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{ return 1; }
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{ return list.count; }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.text = [list objectAtIndex:indexPath.row];
return cell;
}
#end
Reload the table in viewWillAppear method of tableViewController:
[tableViewController.tableView reloadData];
Related
main storyboard imageI have one Table View Controller named "Contacttableviewcontroller" and one View Controller as"Detailviewcontroller". I have 2 text fields in my View Controller to give contact name and number. I have a button to save. When I click on that button, it should display it in Table View Controller. Concept I am using is passing information from destination to source using delegates. Here goes my code which is not working properly.
Detailviewcontroller.h
#protocol detailviewcontrollerdelegate<NSObject>
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile;
#end
#interface DetaiViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *nametextfield;
#property (weak, nonatomic) IBOutlet UITextField *mobiletextfield;
- (IBAction)Save:(id)sender;
#property(nonatomic,weak)id<detailviewcontrollerdelegate>delegate;
Detailviewcontroller.m
- (IBAction)Save:(id)sender {
[self.delegate additem:self.nametextfield.text MOBILE:self.mobiletextfield.text];
}
Contacttableviewcontroller.h
#interface ContactTableViewController : UITableViewController<detailviewcontrollerdelegate>
#property(strong,nonatomic)NSString *contactname;
#property(strong,nonatomic)NSString *contactno;
-(void)reloadtabledata;
#property(strong,nonatomic)NSArray *contactnamearray;
#property(strong,nonatomic)NSArray *contactnoarray;
#end
Contacttableviewcontroller.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 4;
}
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile
{
self.contactname=Name;
self.contactno=Mobile;
self.contactnamearray=#[self.contactname];
self.contactnoarray=#[self.contactno];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellreuse" forIndexPath:indexPath];
cell.textLabel.text=[_contactnamearray objectAtIndex:indexPath.row];
cell.detailTextLabel.text=[_contactnoarray objectAtIndex:indexPath.row];
return cell;
}
-(void)reloadtabledata
{
[self.tableView reloadData];
}
Firstly, you need to check, if you have attached your action method, -Save: to your button or not. You can attach it through the storyboard or programatically. To do it through storyboard, give your button a name like saveButton(not compulsory) and then attach it by ctrl dragging as usual.
Make sure, you attach all the IBOutlets through storyboard properly.
P.S: I have updated the variable's name with proper naming convention. You should also follow the camel case convention while naming your variables.
here is the DetailViewController.h code-
#import <UIKit/UIKit.h>
#protocol DetailViewControllerDelegate;
#interface DetailViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *nameTextField;
#property (weak, nonatomic) IBOutlet UITextField *mobileTextField;
#property(strong, nonatomic) IBOutlet UIButton *savebutton;
- (IBAction)Save:(id)sender;
#property(nonatomic,weak)id<DetailViewControllerDelegate>delegate;
#end
#protocol DetailViewControllerDelegate<NSObject>
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile;
#end
And DetailViewController.m-
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (IBAction)Save:(id)sender {
[self.delegate additem:self.nameTextField.text MOBILE:self.mobileTextField.text];
[self.navigationController popToRootViewControllerAnimated:YES];
}
#end
Now, if you put a break point inside your action method, you will see, it is getting called.
You can see an extra line of code-
[self.navigationController popToRootViewControllerAnimated:YES];
-this is making sure that when you press the save button, it not only sends the data, but also returns to you TableView Controller to show your results.
Now, you need to make sure that your DetailViewController knows who is going to implement its delegate. So, in your ContactTableViewController, wherever, you are initialising your DetailViewController, you have to assign its delegate to self.
So, after a little tweaks, the ContactTableViewController.h class looks like-
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#interface ContactTableViewController : UITableViewController<DetailViewControllerDelegate>
#property(strong,nonatomic)NSString *contactName;
#property(strong,nonatomic)NSString *contactNo;
-(void)reloadtabledata;
#property(strong,nonatomic)NSMutableArray *contactNameArray; //need to be mutable array, so that the data can keep appending
#property(strong,nonatomic)NSMutableArray *contactMobileNoArray; //same as above
#end
Now, there are some small modifications in the file but, the comments should clarify the purpose.
So, the ContactTableViewController.m file looks like
#import "ContactTableViewController.h"
#interface ContactTableViewController ()
#end
#implementation ContactTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
//Make sure you initialize the array before tryig to add any element
self.contactNameArray =[[NSMutableArray alloc]init];
self.contactMobileNoArray=[[NSMutableArray alloc]init];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark-
#pragma mark- TableView Datasource methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.contactNameArray count]; //you need to set the row count as the same as the array elements
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellreuse" forIndexPath:indexPath];
cell.textLabel.text=[self.contactNameArray objectAtIndex:indexPath.row];
cell.detailTextLabel.text=[self.contactMobileNoArray objectAtIndex:indexPath.row];
return cell;
}
-(void)reloadtabledata
{
[self.tableView reloadData];
}
#pragma mark- Segue method
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
[segue.destinationViewController setTitle:#"Add Details"];
DetailViewController *vc = [segue destinationViewController];
vc.delegate=self; // By this, you just told your TableViewController that it is responsible for the implementation of the DetailViewController's delegate
}
#pragma mark- DetailViewController's Delegate method
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile
{
self.contactName=Name;
self.contactNo=Mobile;
[self.contactNameArray addObject:self.contactName]; //added the new entry
[self.contactMobileNoArray addObject:self.contactNo]; //added the new entry
[self.tableView reloadData]; //reload the table right after you updated the arrays
}
#end
This should help you with all your queries. If there is a change in the ContactTableViewController.m file, I added one or more comments. I tried to run the app and this is working properly.
Hey Just add this line in your view did load method of Contacttableviewcontroller.
DetailViewController *detailVc=[DetailViewController alloc]init];
detailVc.delegate =self;
Try this one
detailviewcontrollerdelegate
#import <Foundation/Foundation.h>
#protocol detailviewcontrollerdelegate<NSObject>
- (void)additem:(NSString *)Name MOBILE:(NSString *)Mobile;
#end
Detailviewcontroller.h
#import <UIKit/UIKit.h>
#import "detailviewcontrollerdelegate.h"
#interface DetaiViewController : UIViewController{
id< detailviewcontrollerdelegate > delegate;
}
#property (nonatomic, assign) id< detailviewcontrollerdelegate > delegate;
#property (weak, nonatomic) IBOutlet UITextField *nametextfield;
#property (weak, nonatomic) IBOutlet UITextField *mobiletextfield;
- (IBAction)Save:(id)sender;
and other as u have done make it same
**Detailviewcontroller.m**
- (IBAction)Save:(id)sender {
[self.delegate additem:self.nametextfield.text MOBILE:self.mobiletextfield.text];
}
I am very new to IOS programming and I started with a list application. I used the default Master Detail View template in Xcode, and I am trying to edit that to do a to do list or grocery list.
The idea is to be able to tap the + button on the MasterViewController and it seque to the Add screen, input the information there, tap the Save button and it go back to the MasterViewController with the information input in the add screen populating the Table in the MasterViewController. Then if you tap on the table cell that has been added it will seque to the detailViewController and just show the information.
I have spent a lot of hours searching and reading and I am just not getting what to do. I thought this would be an easy application, but I am getting beat! Any tips or help would be appreciated!
I have three view controllers and an Item Class:
the Master controller that is my table of items;
the detail View controller that will just show details of the table row;
and an add view controller, which I am trying to put all the information in to save to my master controller table.
The seque that goes to my Add view controller is called add
The seque that goes to my Detail view controller is called showDetail
I then have the MasterViewController.h :
#import <UIKit/UIKit.h>
#import "Items.h"
#import "AddViewController.h"
#interface MasterViewController : UITableViewController
#property NSMutableArray *items;
#end
MasterViewController.m
#import "MasterViewController.h"
#import "DetailViewController.h"
#import "Items.h"
#interface MasterViewController ()
#property NSMutableArray *itemsarray;
//#property NSMutableArray *stores;
//#property NSMutableArray *prices;
#end
#implementation MasterViewController
- (void)awakeFromNib {
[super awakeFromNib];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;//this is the edit button on the master controller, top left
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Segues
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"add"]) {
}
if ([segue.identifier isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
DetailViewController *destViewController = segue.destinationViewController;
destViewController.item = [_itemsarray objectAtIndex:indexPath.row];
destViewController.quantity = [_itemsarray objectAtIndex:indexPath.row];
destViewController.store = [_itemsarray objectAtIndex:indexPath.row];
}
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.itemsarray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
Items *toDo = _itemsarray[indexPath.row];
cell.textLabel.text = toDo.name;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[self.itemsarray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
#end
DetailViewController.h
#import <UIKit/UIKit.h>
#include "Items.h"
#interface DetailViewController : UIViewController
#property (strong, nonatomic) id detailItem;
#property (weak, nonatomic) IBOutlet UILabel *item;
#property (weak, nonatomic) IBOutlet UILabel *quantity;
#property (weak, nonatomic) IBOutlet UILabel *store;
#end
DetailViewController.h
#import "DetailViewController.h"
#import "Items.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem {
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
[self configureView];
}
}
- (void)configureView {
// Update the user interface for the detail item.
if (self.detailItem) {
//this is what the text box for name of item will show. it updates
self.item.text= [self.detailItem name] ;
//self.quantity.text= [self.detailItem quantity] ;
//self.store.text= [self.detailItem store] ;
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
AddViewController.h
#import <UIKit/UIKit.h>
#include "Items.h"
#import "MasterViewController.h"
#interface AddViewController : UIViewController
#property (strong, nonatomic) id detailItem;
#property (weak, nonatomic) IBOutlet UITextField *item_text_box;
#property (weak, nonatomic) IBOutlet UITextField *quantity_text_box;
#property (weak, nonatomic) IBOutlet UITextField *store_text_box;
#end
AddViewController.m - This is where I am not sure what to do. I am using the save button to call the insertNewObject function, which is where I don't know how to send this information back to the MasterView Controller (at least this is where I think I have the problem, Im very new, so not sure)
#import "AddViewController.h"
#import "MasterViewController.h"
#interface AddViewController ()
#end
#implementation AddViewController
- (void)viewDidLoad {
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:#selector(insertNewObject:)];
//this is the add button at the top right of master controller
self.navigationItem.rightBarButtonItem = saveButton;
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)insertNewObject:(id)sender {
//this is what happens when we press our save button
//this is what happens when the add button is pushed
if (!self.itemsarray) {
self.itemsarray = [[NSMutableArray alloc] init];
}
[self.itemsarray insertObject:[NSDate date] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
#end
Items.h
#import <Foundation/Foundation.h>
#interface Items : NSObject
#property NSString *name;
#property NSString *store;
#property NSString *section;
#property float price;
+ (Items *)createItemWithName:(NSString *)name andPrice:(float)price andStore: (NSString *)store andSection: (NSString*)section;
#end
Items.m
#import "Items.h"
#implementation Items
#synthesize name = _name;
#synthesize store = _store;
#synthesize price = _price;
#synthesize section = _section;
+ (Items *)createItemWithName:(NSString *)name andPrice:(float)price andStore:(NSString *)store andSection:(NSString*)section{
// Initialize Item
Items *item = [[Items alloc] init];
// Configure Item
[item setName:name];
[item setPrice:price];
[item setStore:store];
[item setStore:section];
return item;
}
#end
This is not homework, I have an app idea and wanted to get some of the basics - this app will resemble a part of what I want to do. Thanks!
I suggest creating a class that will act as your data model instead of juggling data in your controller properties. One way of doing this is to create a singleton object and have the controllers talk to it when they want to add or retrieve items.
Using this strategy, a showDetail segue would only need to tell the data model which item number had been selected and the detail controller would call a selectedItem (or some name) method to retrieve it.
Similarly, the add controller would just update the data model and the master controller would get the new information by referencing the model inside its table delegate/datasource methods.
There are ways to do what you're trying to do by using delegates or notifications, but I think having a class/object that's responsible for the application's data is easier to understand and easier to work with when the app becomes more complex.
You can use any one of the following methods
Delegation
Blocks
Notification
Since you are new to iOS,i suggest you to go with delegation. It's easy and simple
Please go though following links
Using Delegation to Communicate With Other View Controllers
Simple Stackoverflow answer
I am having a bit of trouble getting a button pressed on a ViewController to load a specific lot of information in an array for displaying on a UITableViewController.
I know you can do it with detecting the segue but I have tried this without - I had success. I read somewhere else how I can use tags on the button to identify it and I tried to use this but it only displays one set of data no matter what button I have pressed. I've tried swapping a lot of things around to try and get it to work but to no avail. I have a ViewController with the buttons on it, a TableViewController to display the arrays and a CellViewController to display the better description of the tableview info.
My code is pretty 'all over the shop' at the moment. I haven't included the Cell View controllers as I don't think they have that much relevance with what I want to do at this stage.The buttonviewcontroller is just a normal UIViewController and both buttons are linked as 'Button1'class in the storyboard. They have been given tags 0 and 1 which I believe is in under the 'view' subheading in the storyboard. Please alert me if this is wrong and I am missing something really obvious but that was the only place I could find 'tag'.
Honestly I don't know exactly what I'm doing in xcode as I'm not very familiar with it but seem to understanding parts of it. However, I'm not sure exactly what I'm doing wrong at the moment.
Code:
ButtonViewController.M (this is where the buttons are)
#import <UIKit/UIKit.h>
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController : UIViewController
-(IBAction) button_Clicked:(id)sender;
#property (strong, nonatomic) IBOutlet UIButton *Button1;
#end
ButtonViewController.m
#import "ButtonViewController.h"
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController ()
#end
#implementation ButtonViewController
-(IBAction) button_Clicked:(id)sender
{
//something here that is going wrong
tableViewController *tableVC = [[tableViewController alloc]initWithNibName:#"tableViewController" bundle:nil];
if(_Button1.tag==0)
{
tableVC.buttonSelected = 0;
}
else if(_Button1.tag==1)
{
tableVC.buttonSelected = 1;
}
[self.navigationController pushViewController:tableVC animated:YES];
[tableVC.tableView reloadData];
#end
tableViewController.h
#import <UIKit/UIKit.h>
#interface tableViewController : UITableViewController
#property (nonatomic, assign) int buttonSelected;
#property (nonatomic, strong) NSArray *Title;
//#property (nonatomic, strong) NSMutableArray *Title;
#property (nonatomic, strong) NSArray *Description;
//#property (nonatomic, strong) NSMutableArray *Description;
//Not sure if Mutable or normal array
#end
tableViewController.m
#import "tableViewController.h"
#import "TableCell.h"
#import "DetailViewController.h"
#import "ButtonViewController.h"
#interface tableViewController ()
#end
#implementation tableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(_buttonSelected == 0)
{
_Title = #[#"Hamstring Muscle Tear",#"Lower Back Pain"];
_Description = #[#"Blahahaha", #"blahahaha2",#"blalalala3"];
[self.tableView reloadData];
}
else if (_buttonSelected == 1)
{
_Title = #[#"1",#"2",#"3"];
_Description = #[#"dededdededde", #"deddedede2",#"blalalala3"];
[self.tableView reloadData];
}
#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 _Title.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
int row = [indexPath row];
cell.TitleLabel.text = _Title[row];
cell.DescriptionLabel.text = _Description[row];
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowDetails"]) {
DetailViewController *detailviewcontroller = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
int row = [myIndexPath row];
detailviewcontroller.DetailModal = #[_Title[row],_Description[row]];
}
}
#end
There are two ways to doing same.
Implement delegate method and call it on event.
You can fire NSPostNotification event from one controller to another controller.
Change the data, then post an NSNotification that it changed.
The table view data source observes the notification and calls [tableView reloadData]
You can find details how to do this in apple's sample code.
Not sure if the above is even my question as I am basically new to using objective-c and iOS and not sure if that's the right wording but anyway...
Basically I have completed this tutorial https://www.youtube.com/watch?v=ITUI7fukRO8 for using a tableView with an array of data.
The substance of the program consists of a navcontroller, tableviewController and a viewController for the extra detail of the table data.
Currently I have a button (from another viewcontroller) that is linking to my tableView.
How would I go about setting up and IF statement in regards to the button pressed (-as I need to link other buttons from other controllers) so that if a specific button is pressed, the array that is displayed in the tableView is different.
I'm currently thinking of doing a bunch of if, then, else statements and just manually changing the detail of the arrays.
Is this the way to go??
Or should I just set up another table view for each of my buttons.
I have a set of .h and .m for the tableCell, tableCellController, and the ViewController.
That probably didn't make a whole lot of sense but if you somewhat understand help would be appreciated.
Cheers
Edit: As you can see my code is pretty 'all over the shop' at the moment. I haven't included the Cell View controllers as I don't think they have that much relevance with what I want to do at this stage.The buttonviewcontroller is just a normal UIViewController and both buttons are linked as 'Button1'class in the storyboard. They have been given tags 0 and 1 which I believe is in under the 'view' subheading in the storyboard. Please alert me if this is wrong and I am missing something really obvious but that was the only place I could find 'tag'. ARRRG Objective-c is frustrating when you don't the language at all./
Updated Code as 21/03.
ButtonViewController.M (this is where the buttons are)
#import <UIKit/UIKit.h>
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController : UIViewController
-(IBAction) button_Clicked:(id)sender;
#property (strong, nonatomic) IBOutlet UIButton *Button1;
#end
ButtonViewController.m
#import "ButtonViewController.h"
#import "tableViewController.h"
#import "TableCell.h"
#interface ButtonViewController ()
#end
#implementation ButtonViewController
-(IBAction) button_Clicked:(id)sender
{
//something here that is going wrong
tableViewController *tableVC = [[tableViewController alloc]initWithNibName:#"tableViewController" bundle:nil];
if(_Button1.tag==0)
{
tableVC.buttonSelected = 0;
}
else if(_Button1.tag==1)
{
tableVC.buttonSelected = 1;
}
[self.navigationController pushViewController:tableVC animated:YES];
[tableVC.tableView reloadData];
#end
tableViewController.h
#import <UIKit/UIKit.h>
#interface tableViewController : UITableViewController
#property (nonatomic, assign) int buttonSelected;
#property (nonatomic, strong) NSArray *Title;
//#property (nonatomic, strong) NSMutableArray *Title;
#property (nonatomic, strong) NSArray *Description;
//#property (nonatomic, strong) NSMutableArray *Description;
//Not sure if Mutable or normal array
#end
tableViewController.m
#import "tableViewController.h"
#import "TableCell.h"
#import "DetailViewController.h"
#import "ButtonViewController.h"
#interface tableViewController ()
#end
#implementation tableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if(_buttonSelected == 0)
{
_Title = #[#"Hamstring Muscle Tear",#"Lower Back Pain"];
_Description = #[#"Blahahaha", #"blahahaha2",#"blalalala3"];
[self.tableView reloadData];
}
else if (_buttonSelected == 1)
{
_Title = #[#"1",#"2",#"3"];
_Description = #[#"dededdededde", #"deddedede2",#"blalalala3"];
[self.tableView reloadData];
}
#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 _Title.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableCell";
TableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
int row = [indexPath row];
cell.TitleLabel.text = _Title[row];
cell.DescriptionLabel.text = _Description[row];
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"ShowDetails"]) {
DetailViewController *detailviewcontroller = [segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView indexPathForSelectedRow];
int row = [myIndexPath row];
detailviewcontroller.DetailModal = #[_Title[row],_Description[row]];
}
}
#end
Do a CTRL - drag in Storyboard to create a IBAction for the button.
In the IBAction method, get the data you want for your data arrays (Images, Title, Description ref the tutorial you linked). Then call:
[tableview reloadData]
This will repopulate the tableview.
I am new at Objective-C, and I'm trying to understand delegates. I have searched and read a lot, but nothing is really helping me understand. I think that best way to understand this might be asking a question with a sample app.
I'm trying to create a grade calculator application to test my skills. Here are my files:
mainTableViewController.h
#import <UIKit/UIKit.h>
#interface mainTableViewController : UITableViewController
#end
mainTableViewController.m
#import "mainTableViewController.h"
#import "addLectureViewController.h"
#interface mainTableViewController ()
#end
#implementation anaTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
[lectureName count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
}
#end
addLectureViewController.h
#import <UIKit/UIKit.h>
#interface addLectureViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *lectureNameTextField;
- (IBAction)addButtonPressed:(id)sender;
#property NSMutableArray *lectureName;
#property NSObject *lecture;
#end
addLectureViewController.m
#import "addLectureViewController.h"
#interface addLectureViewController ()
#end
#implementation addLectureViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_lectureName = [[NSMutableArray alloc] init];
_lecture = [[NSObject alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (IBAction)addButtonPressed:(id)sender {
_lecture = _lectureNameTextField.text;
[_lectureName addObject:_lecture];
NSLog(#"%#",_lectureName);
}
#end
Everything is okay so far. But when i try to use the _lectureName NSMutableArray at mainTableViewController.m, I can't see the array.
I know the codes for printing the array in tableView. I know they are not at there right now. I just don't understand implement delegate codes to my code.
If You want to display something on the rows of the table, You can take an NSArray and you have to return the count of the array in the delegate method:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return array.count;
}
Otherwise, table will not display any elements. And delegate method cellForRowAtIndexPath will only be called if you are returning a particular array count of number count in your numberOfRowsInSection method.
You can take reference from these links to understand delegates:
http://www.tutorialspoint.com/ios/ios_delegates.htm
How do I set up a simple delegate to communicate between two view controllers?
http://code.tutsplus.com/tutorials/ios-sdk-custom-delegates--mobile-10848
But in the case of tableView, the delegate methods are internally defined and triggered internally. We just need to set those delegates to the controller which acts as a listener.
The below code might have syntax errors but they can provide a summary of delegates for this code.
Make the following changes :-
mainTableViewController.h
#import <UIKit/UIKit.h>
#interface mainTableViewController : UITableViewController
#property(strong, nonatomic) NSMutableArray *lectureName
#end
Synthesize the property lectureName in mainTableViewController.m
Then make the following changes in addLectureViewController.h
#import <UIKit/UIKit.h>
#import "mainTableViewController.h"
#interface addLectureViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *lectureNameTextField;
- (IBAction)addButtonPressed:(id)sender;
#property(weak, nonatomic) id<mainTableViewController> delegate;
#property NSMutableArray *lectureName;
#property NSObject *lecture;
#end
Synthesize the property delegate in addLectureViewController.m
Then make the following change :-
- (IBAction)addButtonPressed:(id)sender {
_lecture = _lectureNameTextField.text;
[_lectureName addObject:_lecture];
NSLog(#"%#",_lectureName);
delegate.lectureName=_lectureName;
}
Assuming that you are pushing addLectureViewController from mainTableViewController, also include the following code in prepareForSegue of mainTableViewController (or whatever method in which you are pushing addLectureViewController). :-
addLectureViewController *vc=[[addLectureViewController alloc] init];
vc.delegate=self;
// Push vc
The above code actually creates a weak property of type id<mainTableViewController> called delegate (weak in order to prevent reference cycles). This way, addLectureViewController can update mainTableViewController's property.
Points:
Why is the class in mainTableViewController.m named anaTableViewController. It should be mainTableViewController (almost always, until you get more advanced).
mainTableViewController and addLectureViewController should start with capital letters.
The only way for mainTableViewController to access lecture is through a addLectureViewController object, e.g.
addLectureViewController *alvc = // *something* here
NSArray *localLecture = [alvc lecture];
Figure out how you have access to an addLectureViewController and you will have solved your problem.