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;
}
Related
I want to send the information from Players View Controller to Current Match View Controller using a delegate. The only thing is that PlayersViewCotroller and GameDetailsViewController are seperated by another view controller. What should I do to make sure that the selector is being called? Am I missing anything?
#import <UIKit/UIKit.h>
#class PlayersViewController;
#protocol PlayersViewControllerDelegate <NSObject>
- (void)addItemViewController:(PlayersViewController *)controller didFinishEnteringPlayer1:(NSString *)player1 didFinishEnteringPlayer2:(NSString *)player2;
#end
#interface PlayersViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *player1;
#property (weak, nonatomic) IBOutlet UITextField *notes1;
#property (weak, nonatomic) IBOutlet UITextField *player2;
#property (weak, nonatomic) IBOutlet UITextField *notes2;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *nextButton;
- (IBAction)nextButtonPressed:(id)sender;
#property (nonatomic, weak) id <PlayersViewControllerDelegate> pdelegate;
#end
PlayersViewController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqual:#"playersSegue"]) {
if([self.pdelegate respondsToSelector:#selector(addItemViewController:didFinishEnteringPlayer1:didFinishEnteringPlayer2:)]){
[self.pdelegate addItemViewController:self didFinishEnteringPlayer1: player1.text didFinishEnteringPlayer2: player2.text];
NSLog(#"Works");
}
}
CurrentMatchViewController.m (sending the info to this view controller)
- (void)addItemViewController:(PlayersViewController *)controller didFinishEnteringPlayer1:(NSString *)player1 didFinishEnteringPlayer2:(NSString *)player2 {
NSLog(#"%#", player1);
}
I'm building my first iOS app to try and learn iOS coding. However, I need to pass a value xAuthToken from one controller to the other. I can't seem to get it working to. I init the value in the first controller ViewController, but then I need it in SettingsController. I keep getting errors and the one it throws now is: Property 'ViewController' not found on object of type 'ViewController'
What am I doing wrong?
ViewController.h
#import <UIKit/UIKit.h>
#import "SettingsController.h"
#interface ViewController : UIViewController <UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *txtUsername;
#property (weak, nonatomic) IBOutlet UITextField *txtPassword;
- (IBAction)sigininClicked:(id)sender;
- (IBAction)backgroundTap:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic) NSString *xAuthToken;
#end
#implementation ViewController
- (IBAction)sigininClicked:(id)sender {
NSString *xAuthToken = #"0";
self.viewController = [[SettingsController alloc] init];
self.viewController.xAuthToken = xAuthToken;
[self performSegueWithIdentifier:#"login_success" sender:self];
}
SettingsController.h
#import <Foundation/Foundation.h>
#interface SettingsController : UIViewController
#end
SettingsController.m
#interface SettingsController ()
#property (weak, nonatomic) IBOutlet UITextField *myTextField;
#property (weak, nonatomic) IBOutlet UISwitch *mySwitch;
#end
#implementation SettingsController
//THIS IS WHERE I NEED XAUTHTOKEN
If you have a segue that presents your SettingsController, pass the information it needs in prepareForSegue. Don't create a new local SettingsController.
You can do something like
viewController = [self.storyboard instantiateviewcontrollerwithidentifier:#"your vc name"];
viewController.Xauthtoken = data;
// Do something else with this.
Or another way ( I don't know if it's good or bad, use it while your vc is already active ):
Use NSNotificationCenter and pass values between it.
Third way is create delegate for first Viewcontroller.
Try this in your ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic) NSString *xAuthToken;
#end
#implementation ViewController
- (IBAction)sigininClicked:(id)sender {
xAuthToken = #"Your Value Here";
[self performSegueWithIdentifier:#"login_success" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"login_success"]) {
SettingsController *destViewController = segue.destinationViewController;
destViewController.xAuthToken = xAuthToken;
}
}
And in your SettingsController.h
#import <Foundation/Foundation.h>
#interface SettingsController : UIViewController
#property (nonatomic,strong) NSString *xAuthToken;
#end
SettingsController.m
#interface SettingsController ()
#property (weak, nonatomic) IBOutlet UITextField *myTextField;
#property (weak, nonatomic) IBOutlet UISwitch *mySwitch;
#end
#implementation SettingsController
-(void)viewDidLoad{
NSLog("%#",xAuthToken);
}
My destination ViewController has a number of labels and images which need to be changed dependent on the specific previous ViewController. I have a segue set up which should change these but for some reason it is not, even though the segue is being called.
My initial ViewController has a button which has a segue passing to the next ViewController with the name "aName". I'm probably missing something simple but I have been following another section of my code which does the exact same thing and works! I have also tested that the segue is successfully being called with a NSLog which returns fine. All the IBOutlets are also assigned correctly.
Initial View Controller.m:
#import "dViewController.h"
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"aName"]) {
dViewController *dVC = (dViewController *)segue.destinationViewController;
dVC.TitleLabel.text = #"abc";
dVC.1Img.image = [UIImage imageNamed:#"somepath.jpg"];
dVC.2Img.image = [UIImage imageNamed:#"somepath2.jpg"];
[dVC.1Button setTitle:#"abcd" forState:UIControlStateNormal];
[dVC.1Button setTitle:#"efgh" forState:UIControlStateNormal];
}
Destination ViewController:
dViewController.h
#property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
#property (strong, nonatomic) IBOutlet UIImageView *1Img;
#property (strong, nonatomic) IBOutlet UIImageView *2Img;
#property (strong, nonatomic) IBOutlet UIButton *1Button;
#property (strong, nonatomic) IBOutlet UIButton *2Button;
Edit: From doing some more looking around I think I should be using a delegate. It seems quite complicated and not really sure where I start. But I'll have a go at looking at what's in this thread: Changing label's text in another view controller
you have to create a variable for each label you want to change and in viewDidLoad assing the variable to the label.text
for example
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"aName"]) {
dViewController *dVC = (dViewController *)segue.destinationViewController;
dVC.titleString = #"abc";
dVC.1Image = [UIImage imageNamed:#"somepath.jpg"];
dVC.2Image = [UIImage imageNamed:#"somepath2.jpg"];
dVC.1ButtonString=#"ButtonTitle";
dVC.2ButtonString=#"ButtonTitle2";
}
in DestinationController
#property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
#property (strong, nonatomic) IBOutlet UIImageView *1Img;
#property (strong, nonatomic) IBOutlet UIImageView *2Img;
#property (strong, nonatomic) IBOutlet UIButton *1Button;
#property (strong, nonatomic) IBOutlet UIButton *2Button;
#property(strong,nonatomic)NSString *2ButtonString;
#property(strong,nonatomic)UIImage*1Image;
#property(strong,nonatomic)UIImage*2Image;
#property(strong,nonatomic)NSString* titleString;
#property(strong,nonatomic)NSString *1ButtonString;
#property(strong,nonatomic)UIImageView *1Img;
#property(strong,nonatomic)UIImageView *1Img;
- (void)viewDidLoad{
self.TitleLabel.text = self.titleString;
self.1Img.image = self.1Image;
self.2Img.image = self.2Image;
[self.1Button setTitle:self.1ButtonString];
[self.2Button setTitle:self.1ButtonString];
}
hope It help you, the problem is that with
dViewController *dVC = (dViewController *)segue.destinationViewController;
you only bring the controller not the view. and the IBOutlet belongs to the view and the view is not load i hope you understand
Read about app navigation principles. From apple:
https://developer.apple.com/library/ios/documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html
Put parentheses around segue.destinationViewController like this:
dViewController *dVC = (dViewController *)(segue.destinationViewController);
Hi everyone I have been building an app and have met some problems.
My app has two viewControllers. One is MenuViewController and another one is MainViewController.
I want to pass a string from MainViewController to a mutableArray in MenuViewController, but have no idea how.
Here are my codes:
<MenuViewController.h>
#import <UIKit/UIKit.h>
#interface MenuViewController : UITableViewController {
NSMutableArray *secondFavourite;
}
#property (nonatomic, strong) NSMutableArray *secondFavourite;
#end
.
<MenuViewController.m>
#import "MenuViewController.h"
#import "MainViewController.h"
#interface MenuViewController ()
#property (strong, nonatomic) NSArray *menu;
#end
#implementation MenuViewController
#synthesize menu;
#synthesize secondFavourite;
- (void)viewDidLoad
{
[super viewDidLoad];
self.secondFavourite = [[NSMutableArray alloc] init];
self.menu = self.secondFavourite;
}
.
<MainViewController.h>
#import <UIKit/UIKit.h>
#import <social/Social.h>
#interface MainViewController : UIViewController {
IBOutlet UIImageView *imagepost;
UILabel *predictionLabel;
}
- (IBAction)sampleSelector:(UIButton *)sender;
- (IBAction)showAllClick:(id)sender;
#property (nonatomic, retain) IBOutlet UILabel *predictionLabel;
#property (strong, nonatomic) NSArray *predictionArray;
#property (strong, nonatomic) UIButton *menuBtn;
#property (strong, nonatomic) NSMutableArray *fav;
#property (strong, nonatomic) IBOutlet UILabel *favLabel;
#property (strong, nonatomic) IBOutlet UITableView* tableView;
#property (nonatomic, strong) NSMutableArray *favourite;
#end
.
<MainViewController.m>
- (void)viewDidLoad
{
[super viewDidLoad];
self.predictionArray = [[NSArray alloc] initWithObjects:#"Hey gurl", nil];
}
//Add to favourite
- (void) addToFav {
self.favourite = [[NSMutableArray alloc] init];
[self.favourite addObject:self.predictionLabel.text];
[self.tableView reloadData];
NSLog(#"%#", self.favourite);
}
//add to favourite button action
- (IBAction)addToFavButton:(id)sender {
[self addToFav];
//pass data from favourite here to secondFacourite in MenuViewController (found on stack overflow)
MenuViewController *menuViewController = [[MenuViewController alloc]initWithNibName:#"MenuViewController" bundle:nil];
menuViewController.secondFavourite = [[NSMutableArray alloc]initWithArray:self.favourite];
[self.navigationController pushViewController:menuViewController animated:YES];
}
I used NSLog to check that the menuViewController.secondFavourite in MainViewController successfully added the string into the array, isn't the array the same array in MenuViewController? Why doesn't the menu.tableView update and show the new string added? I am very confused and I hope someone will help me out.
Thanks for reading this.
This has to do with the fact that your menu viewDidLoad is overwriting the value in these two lines:
self.secondFavourite = [[NSMutableArray alloc] init];
self.menu = self.secondFavourite;
That first line is setting your secondFavourite property to an empty NSMutableArray instance. And since viewDidLoad will be called only after the view has been loaded into memory (in this case, when you try to push the view controller onto the stack), your initial values in the secondFavourite property will be lost.
Instead, you should move that initialization code into the an init method.
I've got 2 views. The firstView and the secondView. The firstView needs the favourites array from the secondView, so I try to call the getFavourites method defined in the protocol. This returns null however, which seems strange to me because everything makes sense.
Here is the firstViewController.h:
#import <UIKit/UIKit.h>
#import "Drink.h"
#protocol firstViewControllerDelegate;
#interface FirstViewController : UIViewController
{
id <firstViewControllerDelegate> delegate;
NSMutableArray *labels;
UIButton *button1;
UIButton *button2;
UIButton *button3;
UIButton *button4;
}
- (IBAction) buttonClick: (id) sender;
#property (nonatomic, assign) id <firstViewControllerDelegate> delegate;
#property (nonatomic, retain) IBOutlet UIButton *button1;
#property (nonatomic, retain) IBOutlet UIButton *button2;
#property (nonatomic, retain) IBOutlet UIButton *button3;
#property (nonatomic, retain) IBOutlet UIButton *button4;
#end
#protocol firstViewControllerDelegate
- (NSMutableArray *) getFavourites;
- (void) setFavourites: NSMutableArray;
#end
firstViewController.m
#synthesize delegate;
.......
- (void) viewWillAppear:(BOOL)animated
{
NSMutableArray *favourites = [delegate getFavourites]; // favourites is empty after this line
[button1 setTitle:[[favourites objectAtIndex:1] name] forState:UIControlStateNormal];
NSLog(#"VIEW APPEARED. BUTTON TITLE IS: %#", button1.currentTitle);
}
SecondViewController.h
#import <UIKit/UIKit.h>
#import "FirstViewController.h"
#interface SecondViewController: UIViewController <UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, firstViewControllerDelegate>
{
NSMutableArray *favourites;
NSMutableArray *drinks;
}
#property (nonatomic, retain) NSMutableArray *drinks;
#property (nonatomic, retain, getter = getFavourites) NSMutableArray *favourites;
- (void) addDrink: (NSString *) name;
#end
Does anybody have any idea why this isn't working?
Are you sure you're setting the delegate property of FirstViewController? i.e.:
FirstViewController *firstController = // Instantiate the controller;
firstController.delegate = secondController;
[self.navigationController pushViewController:firstController animated:YES];
secondController should exist before instantiation, otherwise you're setting a nil value