I have UITableViewController in my storyboard in which there are three cell with on label in the middle on each.
For instance if a user clicks on the first cell label in show a another tableview with list of Items by selecting an item it get back to the previous tableView and the item name should be printed in the place of the label.
#import <UIKit/UIKit.h>
#interface carSelectCellTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *carMake;
#property (weak, nonatomic) IBOutlet UILabel *carModel;
#property (weak, nonatomic) IBOutlet UILabel *carRego;
#property (weak, nonatomic) IBOutlet UILabel *carYear;
//the below label are the labels in the cells.
#property (weak, nonatomic) IBOutlet UILabel *carSelected;
#property (weak, nonatomic) IBOutlet UILabel *location;
#property (weak, nonatomic) IBOutlet UILabel *service;
#end
#import "BookService.h"
#import <Parse/Parse.h>
#import "carSelectCellTableViewCell.h"
#interface BookService ()
#end
#implementation BookService
#synthesize tableView;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.tableView.delegate = self;
self.tableView.dataSource = self;
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cell tabbed");
PFObject *temp = [customerCars objectAtIndex:indexPath.row];
NSLog(#"%#", temp.objectId);
NSString *car = temp.objectId;
UIStoryboard *dashboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *change = [dashboard instantiateViewControllerWithIdentifier:#"bookAservice"];
[self presentViewController:change animated:YES completion:nil];
static NSString *Identifier = #"carSelectedCell";
//here is where i'm calling the cell to change the label value when the selection is made. before dequeueReusableCellWithIdentifier there should be appropriate tableView Table.
carSelectCellTableViewCell *cell2 = [dequeueReusableCellWithIdentifier:Identifier];
cell2.carSelected.text = #"selcted";
}
How can i programmatically initiate the tableView. So that i can change the cell label value to the selected item.
Now If u suppose the First table View is names as ParentViewController and the second table view as childView u can do the Foll:
To do this make ParentController a delegate of ChildController. This allows ChildController to send a message back to ParentController enabling us to send data back.
For ParentController to be delegate of ChildController it must conform to ChildController's protocol which we have to specify. This tells ParentController which methods it must implement.
In ChildController.h, below the #import, but above #interface you specify the protocol.
#class ChildController;
#protocol ViewControllerBDelegate <NSObject>
- (void)addItemViewController:(ChildController *)controller didFinishEnteringItem:(NSString *)item;
#end
next still in the ChildController.h you need to setup a delegate property in ChildController.h
#property (nonatomic, weak) id <ChildControllerDelegate> delegate;
In ChildController we call a message on the delegate when we pop the view controller.
For this case the following will be called in didSelectRowAtIndex method
NSString *itemToPassBack = #"Pass this value back to ParentController";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
That's it for ChildController. Now in ParentController.h, tell ParentViewController to import Child and conform to its protocol.
import "ChildController.h"
#interface ParentController : UIViewController
In ParentController.m implement the following method from our protocol
- (void)addItemViewController:(ChildController *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(#"This was returned from ChildController %#",item);
}
The last thing we need to do is tell ChildController that ParentController is its delegate before we push ChildController on to nav stack.
ChildController *ChildController = [[ChildController alloc] initWithNib:#"ChildController" bundle:nil];
ChildController.delegate = self
[[self navigationController] pushViewController:ChildController animated:YES];
Related
I created a custom UIView with the buttons above , this view opens as a pop- up to a viewcontroller . I want the view controller intercepts the pressure of the buttons so I created a protocol methods but delegates in the view controller is never called.
The protocol:
#protocol InsertDelegate <NSObject>
-(void)addNode:(double)x pointY:(double)y radius:(double)r forw:(int)forw;
-(void)cancelView:(UIView*)view;
#end
In the AddNewNode.h
#interface AddNewNode : UIView
#property (assign, nonatomic)id <InsertDelegate> delegate;
- (IBAction)actionCancel:(id)sender;
- (IBAction)actionAdd:(id)sender;
#end
In the AddNewNode.m
- (IBAction)actionCancel:(id)sender { //this action is connect with storyboard
NSLog(#"%#", self.delegate);
//(null)
[self.delegate cancelView:self];
}
- (IBAction)actionAdd:(id)sender { //this action is connect with storyboard
NSLog(#"%#", self.delegate);
//(null)
[self.delegate addNode:x pointY:y radius:r forw:f];
}
In ViewController.h:
#interface ViewController : UIViewController <InsertDelegate>
In ViewController.m
(IBAction)addNewNode:(id)sender {
AddNewNode * addRowView =[[AddNewNode alloc]init];
addRowView.delegate=self;
[self.view addSubview: addRowView];
}
//delegate methods never called
-(void)addNode:(double)x pointY:(double)y radius:(double)r forw:(int)forw{
}
-(void)cancelView:(UIView*)view{
}
In UIView custom self.delegate become null and I don't understand why
What about making an IBOutlet for your
ViewController.h
#interface ViewController : UIViewController <InsertDelegate>
#property (strong, nonatomic) AddNewNode * addNewNode;
//or connect IBOutlet of your `addNewNode`
#property (strong, nonatomic) IBOutlet (addNewNode);
#end
ViewController.m
- (IBAction)addNewNode:(id)sender
{
// you dont need to allocate anymore
self.addRowView.delegate=self;
// and you need to trigger the delegate from `- (IBAction)actionAdd:(id)sender;`
[self.addRowView actionAdd:sender];
}
try the following
Create a private property to hold the instance
#implement AddNewNode()
#propery (nonatomic, strong) AddNewNode * addNewNode;
#end
from inside the button handler
(IBAction)addNewNode:(id)sender {
self.addNewNode =[[AddNewNode alloc]init];
self.addRowView.delegate=self;
}
In my iOS application, I have a main View Controller with three buttons, which work like a tab bar: when I click one of the buttons, a new view controller is invoked.
I tried to implement this via container view containers, so I tried following this guide (http://www.thinkandbuild.it/working-with-custom-container-view-controllers/) and invoke the presentDetailController method in the viewDidLoad of the main controller.
Actually, no views are showed: someone can help me figuring out why? Thanks.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIButton *btnOne;
#property (weak, nonatomic) IBOutlet UIButton *btnTwo;
#property (weak, nonatomic) IBOutlet UIButton *btnThree;
#property (weak, nonatomic) IBOutlet UIView *detailView;
- (IBAction)click:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#import "FirstViewController.h"
#interface ViewController ()
#property UIViewController *currentDetailViewController;
#end
#implementation ViewController
#synthesize btnOne, btnTwo, btnThree;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
FirstViewController *fvc = [[FirstViewController alloc]initWithString:#"I'm the first Controller!"];
[self presentDetailController:fvc];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)click:(id)sender
{
// button selection stuff
[self addDetailController:sender];
}
- (void)presentDetailController:(UIViewController*)detailVC{
//0. Remove the current Detail View Controller showed
if(self.currentDetailViewController){
[self removeCurrentDetailViewController];
}
//1. Add the detail controller as child of the container
[self addChildViewController:detailVC];
//2. Define the detail controller's view size
detailVC.view.frame = [self frameForDetailController];
//3. Add the Detail controller's view to the Container's detail view and save a reference to the detail View Controller
[self.detailView addSubview:detailVC.view];
self.currentDetailViewController = detailVC;
//4. Complete the add flow calling the function didMoveToParentViewController
[detailVC didMoveToParentViewController:self];
}
- (void)removeCurrentDetailViewController{
//1. Call the willMoveToParentViewController with nil
// This is the last method where your detailViewController can perform some operations before neing removed
[self.currentDetailViewController willMoveToParentViewController:nil];
//2. Remove the DetailViewController's view from the Container
[self.currentDetailViewController.view removeFromSuperview];
//3. Update the hierarchy"
// Automatically the method didMoveToParentViewController: will be called on the detailViewController)
[self.currentDetailViewController removeFromParentViewController];
}
- (CGRect)frameForDetailController{
// newFrame's height should be currentFrame's height minus buttons' height
CGRect detailFrame = CGRectMake(0, 0, self.detailView.bounds.size.width, self.detailView.bounds.size.height-self.btnOne.frame.size.height);
return detailFrame;
}
- (void)addDetailController:(id)sender {
FirstViewController *detailVC = [[FirstViewController alloc]initWithString:#"First button clicked"];
[self presentDetailController:detailVC];
}
#end
FirstViewController.h
#import <UIKit/UIKit.h>
#class ViewController;
#interface FirstViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (weak, nonatomic) IBOutlet UIButton *btnOne;
#property (weak, nonatomic) IBOutlet UIButton *btnTwo;
#property (weak, nonatomic) IBOutlet UIButton *btnThree;
- (id)initWithString:(NSString*)string;
#end
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController (){
NSString *text;
}
#end
#implementation FirstViewController
- (id)initWithString:(NSString*)string {
self = [super init];
if(self){
text = string;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.label.text = text;
}
#end
As part of creating FirstViewController, you are calling [super init] which produces a bare UIViewController. From your diagram, it seems as if you want to load a FirstViewController from your storyboard instead.
I suggest a sequence where you create your controller using instantiateViewControllerWithIdentifier:, then set a string property in the controller that you want to use as the label, and finally assign the string to the label when the controller's view loads.
I am making an app that will help people with certain health conditions manage their medication. I have created a modal to add medication which works and saves the new medication using core data.
I am now trying to allow people to edit their medication after it has been saved. To do this I am trying to send a managed object of the medication to a "fibromappMedsEditViewController" and assign the information in the viewDidLoad method of the class.
I keep getting this error:
'NSInvalidArgumentException', reason: '-[UINavigationController setMed:]: unrecognized selector sent to instance 0x746dda0'
Could anybody tell me what I am doing wrong?
relevant methods in fibromappMedsListViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{ //selMed declared at top of file as NSManagedObject *selMed;
selMed = [self.meds objectAtIndex:indexPath.row];
NSLog(#"SELECTED MED: %#",[selMed valueForKey:#"name"] );
UIStoryboardSegue *segueString = [NSString stringWithFormat:#"%#",#"editMeds"];
NSLog(#"%#",segueString);
[self performSegueWithIdentifier:#"editMeds" sender:indexPath];
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
NSLog(#"%#",segue.destinationViewController);
NSLog(#"%#",[selMed valueForKey:#"name"] );
fibroMappMedsEditViewController *dest = segue.destinationViewController;
dest.med = selMed;
}
The fibroMappMedsEditViewController.h
#import <UIKit/UIKit.h>
#interface fibroMappMedsEditViewController : UITableViewController
- (IBAction)saveChanges:(id)sender;
- (IBAction)deleteBtnPressed:(id)sender;
- (IBAction)dosageChanged:(id)sender;
- (IBAction)maxDosageChanged:(id)sender;
- (IBAction)cancel:(id)sender;
- (IBAction)typeChanged:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *tbName;
#property (weak, nonatomic) IBOutlet UITextField *tbDose;
#property (weak, nonatomic) IBOutlet UITextField *tbMaxDose;
#property (weak, nonatomic) IBOutlet UITextField *tbType;
#property (weak, nonatomic) IBOutlet UIStepper *stepperDose;
#property (weak, nonatomic) IBOutlet UIStepper *stepperMaxDose;
#property (weak, nonatomic) IBOutlet UISegmentedControl *changeMeasure;
#property (strong, nonatomic) NSManagedObject *med;
#end
The fibroMappMedsEditViewController.m - just the parts I altered that affect the way the controller loads
#import "fibroMappMedsEditViewController.h"
#import "fibroMappAppDelegate.h"
#import <CoreData/CoreData.h>
#interface fibroMappMedsEditViewController ()
#end
#implementation fibroMappMedsEditViewController
#synthesize tbName;
#synthesize tbDose;
#synthesize tbMaxDose;
#synthesize tbType;
#synthesize med;
double dose;
double maxDose;
- (void)viewDidLoad
{
[super viewDidLoad];
tbName.text = [med valueForKey:#"name"];//name is a string in the model
tbDose.text = [med valueForKey:#"dose"];//dose is a double in the model
tbMaxDose.text = [med valueForKey:#"maxDose"];//maxDose is a double in the model
tbType.text = [med valueForKey:#"type"];//type is a string in the model
}
If you need to see anything else please just ask.
Also, I am using storyboards for this app.
It appears from that log, that your fibroMappMedsEditViewController (which should start with a capital letter BTW) is embedded in a navigation controller. You need to get to that navigation controller's root view controller.
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
UINavigationController *nav = segue.destinationViewController;
fibroMappMedsEditViewController *dest = (fibroMappMedsEditViewController *)nav.topViewController;
dest.med = selMed;
}
I am using static UITableView to show profile of a customer.
It has SelectCountryCell to select country which, when clicked, opens new UITableView with country list.
When I select country from Country TableView, It should display in previous TableView's SelectCountryCell.
How do I do this?
You should bind the static cells to outlets in your UITableViewController and put the profile syncing methods to the - viewWillAppear method.
When the user changes the country in the Country list the profile updates. After that when the user moves back to the UITableViewController instance with static content the profile data will be automatically updated.
You can define a delegate in your CityTableView and then define a method in this delegate.
You should realize this method in your CountryTableView.
Then you may get what you want.
I only offer you a thought. You should find the detail by yourself.
MasterViewController.h
#import "DetailViewController.h"
#interface MasterViewController : UITableViewController <DetailProtocol> // Note this.
#property (strong, nonatomic) DetailViewController *detailViewController;
#property (strong, nonatomic, readwrite) NSString *selectedCountry;
#end
MasterViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!self.detailViewController) {
self.detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
}
self.detailViewController.delegate = self; // THIS IS IMPORTANT...
[self.navigationController pushViewController:self.detailViewController animated:YES];
}
// Note this -- It's a delegate method implementation
- (void)setCountry:(NSString *)country
{
self.selectedCountry = country;
}
DetailViewController.h
#protocol DetailProtocol <NSObject>
-(void)setCountry:(NSString *)country;
#end
#interface DetailViewController : UIViewController
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#property (unsafe_unretained) id <DetailProtocol> delegate; // Note this
#end
DetailViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.delegate setCountry:[countries objectAtIndex:indexPath.row]]; // Note this
[self.navigationController popViewControllerAnimated:YES];
}
My function [ViewController.tableView reloadData] does not work, although I implemented #class ViewController in the .h file and imported #import "ViewController.h" in the .m file.
What am I doing wrong??
--- EDIT ---
Here's my .h file:
#class XMLAppDelegate, XMLProductDetailView;
#interface XMLViewController : UITableViewController <UIScrollViewDelegate, XMLImageDownloaderDelegate> {
NSMutableDictionary *imageDownloadsInProgress;
XMLAppDelegate *appDelegate;
XMLProductDetailView *productDetailView;
IBOutlet UISearchBar *searchBar;
IBOutlet UITableView *tableView;
}
#property (nonatomic, retain) NSMutableDictionary *imageDownloadsInProgress;
#property (nonatomic, retain) IBOutlet UISearchBar *searchBar;
#property (nonatomic, retain) IBOutlet UITableView *tableView;
- (void)imageDidLoad:(NSIndexPath *)indexPath;
#end
But notice: when I include IBOutlet UITableView *tableView;, it hides an instance variable.
UITableViewController already has a property named tableView. Rename your property to something like myTableView and you should be OK.
ViewController it is class name. You should init instance variable of this class
ViewController *vc = [[ViewController alloc] init];
then push it on navigation controller (if it present)
vc.myDataForTable = [NSArray .....]; //for example
[self.navigationController pushViewController:vc animated:YES];
release vc if arc is not used
[vc release];