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
Related
I am creatinng an instance of a View like this...
- (IBAction)findPatientTapped:(id)sender {
RequestDialogViewController *findPatientViewController = [[RequestDialogViewController alloc] initWithNibName:#"RequestDialogViewController" bundle:nil];
findPatientViewController.delegate = self;
findPatientViewController.autoCorrectOff = YES;
findPatientViewController.defaultResponse = #"";
findPatientViewController.keyboardType = #"ASCII";
findPatientViewController.returnKeyType = #"Go";
findPatientViewController.tag = findRequestTag;
findPatientViewController.editSet = YES;
findPatientViewController.titleText = #"Find Patient";
findPatientViewController.messageText =#"Enter all or a portion of the patient's name...";
findPatientViewController.messageText2 = #"Last Name...";
findPatientViewController.messageText3 = #"First Name...";
findPatientViewController.showResponse2 = YES;
findPatientViewController.showNavBarSaveButton = NO;
findPatientViewController.infoTextFile = #"";
findPatientViewController.view.frame = CGRectMake(280, 230, 480, 300);
[self.view addSubview:findPatientViewController.view];
}
The view contains 2 UITextField fields for entry by the user. This all worked fine before running the convert to ARC tool. After the conversion the view crashes when trying to enter a value in either of the 2 fields with...
-[RequestDialogViewController respondsToSelector:]: message sent to deallocated instance
Here is the .h file of the UIViewController after running the conversion to ARC tool...
#import <UIKit/UIKit.h>
#protocol RequestDialogViewControllerDelegate;
#interface RequestDialogViewController : UIViewController <UITextFieldDelegate>{
id<RequestDialogViewControllerDelegate> __weak delegate;
IBOutlet UINavigationBar *navBar;
IBOutlet UITextField *response;
IBOutlet UITextField *response2;
IBOutlet UILabel *message;
IBOutlet UILabel *message2;
IBOutlet UILabel *message3;
IBOutlet UIButton *saveButton;
NSTimer *selectAllTimer;
NSString *defaultResponse;
NSString *titleText, *infoTextFile;
NSString *messageText, *messageText2, *messageText3;
NSString *placeHolderText;
NSString *keyboardType, *returnKeyType;
BOOL editSet, showSaveButton,showNavBarSaveButton, showResponse2, autoCorrectOff;
int tag;
}
#property (weak) id<RequestDialogViewControllerDelegate> delegate;
#property (nonatomic, strong)IBOutlet UITextField *response;
#property (nonatomic, strong) IBOutlet UITextField *response2;
#property (nonatomic, strong)IBOutlet UILabel *message;
#property (nonatomic, strong)IBOutlet UILabel *message2;
#property (nonatomic, strong) IBOutlet UILabel *message3;
#property (nonatomic, strong)IBOutlet UIButton *saveButton;
#property (nonatomic, strong)NSString *defaultResponse;
#property (nonatomic, strong)NSString *titleText, *infoTextFile;
#property (nonatomic, strong)NSString *messageText, *messageText2, *messageText3;
#property (nonatomic, strong)NSString *placeHolderText;
#property (nonatomic, strong)NSString *keyboardType, *returnKeyType;
#property (nonatomic, strong)IBOutlet UINavigationBar *navBar;
#property (readwrite)BOOL editSet, showSaveButton, showNavBarSaveButton, showResponse2, autoCorrectOff;
#property (readwrite)int tag;
#property (nonatomic, strong) NSTimer *selectAllTimer;
- (IBAction)saveButtonPressed:(id)sender;
- (void)selectAll;
- (IBAction)editingDidEnd:(id)sender;
#end
#protocol RequestDialogViewControllerDelegate <NSObject>
#optional
- (void)requestDialogViewDidDismiss:(RequestDialogViewController *)controller withResponse:(NSString*)reqResponse response2:(NSString*)reqResponse2;
#end
Here is the pertenant references in the .h file of the class creating the instance of the RequestDialog view...
#import "RequestDialogViewController.h"
#interface OrthoViewController : UIViewController <RequestDialogViewControllerDelegate>{
}
- (void)requestDialogViewDidDismiss:(RequestDialogViewController *)controller withResponse:(NSString*)reqResponse response2:(NSString*)reqResponse2;
#end
What do I need to do to make this work under ARC? I am thinking it might have something to do with how the protocol is formed.
Thanks,
John
**** Thanks to Dan I resolved this by making findPatientViewController a property of the calling class...
RequestDialogViewController *findPatientViewController;
#implementation OrthoViewController
- (IBAction)findPatientTapped:(id)sender {
findPatientViewController = [[RequestDialogViewController alloc] initWithNibName:#"RequestDialogViewController" bundle:nil];
//set all the properties and add the subview
}
#end
Your findPatientViewController has nothing retaining it, so it gets deallocated at the end of the method where you create it. Then, when something in it's view tries to call a delegate method on it you get that crash.
If findPatientTapped is a method in a view controller then you should add the findPatientViewController as a child view controller. If it's in a view, then you need to least store the findPatientViewController in a property so it doesn't get deallocated while you are still using it.
Your code didn't really work properly before ARC, you just had a memory leak.
I am trying to set up a WKInterfaceTable. I followed Apples docs. My Label is not getting text and I get this error message in console:
Cannot specify setter 'setTitle:' for properties of NSObject or WKInterfaceController
How can I fix this? Objective-C please. Here s my code:
.h
#import <Foundation/Foundation.h>
#import <WatchKit/WatchKit.h>
#interface MainRowType : NSObject
#property (strong, nonatomic) IBOutlet WKInterfaceImage *image;
#property (strong, nonatomic) IBOutlet WKInterfaceLabel *title;
#end
.m
#import "MainRowType.h"
#implementation MainRowType
#end
.h
#import <WatchKit/WatchKit.h>
#import <Foundation/Foundation.h>
#import "MainRowType.h"
#interface WatchTableController : WKInterfaceController
#property (strong, nonatomic) IBOutlet WKInterfaceTable *tableView;
#property (strong, nonatomic) NSMutableArray *titleArray;
#end
.m
I call this method
- (void)configureTableWithData:(NSMutableArray*)dataObjects {
[self.tableView setNumberOfRows:[dataObjects count] withRowType:#"mainRowType"];
for (NSInteger i = 0; i < self.tableView.numberOfRows; i++) {
MainRowType* theRow = [self.tableView rowControllerAtIndex:i];
NSString *titleString = [dataObjects objectAtIndex:i];
[theRow.title setText:titleString];
}
}
Thanks
Your title property is the problem. You can't name a property "title" in those classes. Change the property name and you should be all set.
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);
}
I am trying to use Delegates to communicate thru view controllers. Here is my code:
#protocol ViewControllerDelegate;
#interface ViewController : UIViewController <UITextFieldDelegate>{
IBOutlet UIDatePicker *dateTimePicker;
}
#property (nonatomic, strong) IBOutlet UITextField *className;
#property (nonatomic, strong) IBOutlet UITextField *assignmentTitle;
#property (nonatomic, strong) IBOutlet UITextField *assignmentDescription;
#property (nonatomic, strong) IBOutlet UISwitch *procrastinationNotificationSwitch;
#property (nonatomic, strong) IBOutlet UILabel *notificationOnOffLabel;
#property (nonatomic, assign) id <ViewControllerDelegate> delegate;
#property (nonatomic,strong)classObject *classObject;
-(IBAction) addButton:(id)sender;
#end
#protocol ViewControllerDelegate <NSObject>
-(void)assignmentSaved:(classObject *)classObj;
In action:
[self.delegate assignmentSaved:self.classObject];
In other view controller:
-(ViewController *)vc
{
if (!_vc) {
_vc = [[ViewController alloc]init];
}
return _vc;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.vc.delegate = self;
}
-(void)assignmentSaved:(classObject *)classObj
{
NSLog(#"%#",classObj.description);
classObj2 = classObj;
[self.tableView reloadData];
}
vc is a property of View Controller. When I NSLog the delegate, the delegate ends up to be nil. Also I tried #mialkan answer yet it still does not work. If you need any more info just ask.
I made some changes in your code, and dont forget to #synthesize delegate; and dont for get to setDelegate:self where you create ViewController.
#protocol ViewControllerDelegate;
#interface ViewController : UIViewController <UITextFieldDelegate>{
IBOutlet UIDatePicker *dateTimePicker;
id <ViewControllerDelegate> delegate;
}
#property (nonatomic, strong) IBOutlet UITextField *className;
#property (nonatomic, strong) IBOutlet UITextField *assignmentTitle;
#property (nonatomic, strong) IBOutlet UITextField *assignmentDescription;
#property (nonatomic, strong) IBOutlet UISwitch *procrastinationNotificationSwitch;
#property (nonatomic, strong) IBOutlet UILabel *notificationOnOffLabel;
#property (nonatomic, assign) id <ViewControllerDelegate> delegate;
#property (nonatomic,strong)classObject *classObject;
-(IBAction) addButton:(id)sender;
#end
#protocol ViewControllerDelegate
-(void)assignmentSaved:(classObject *)classObj;
#end
In the first view did you subscribe to your delegate < ViewControllerDelegate > ?
MyOtherViewController : UIViewController <ViewControllerDelegate>
and you can only do that :
- (void)viewDidLoad
{
[super viewDidLoad];
if (!_vc)
_vc = [[ViewController alloc]init];
self.vc.delegate = self;
}
I'm trying to creating a custom UIView, lets call it FooView.
FooView.h
#import <UIKit/UIKit.h>
#interface FooView : UIView
#property (nonatomic, strong) UITextField *barTextField;
#property (nonatomic, strong) UIButton *submitButton;
#end
FooView.m
#import "FooView.h"
#implementation FooView
#synthesize barTextField = _barTextField;
#synthesize submitButton = _submitButton;
...
#end
FooViewController.h
#import <UIKit/UIKit.h>
#import "FooView.h"
#interface FooViewController : UIViewController
#property (nonatomic, strong) FooView *fooView;
#end
FooViewController.m
#import "SearchViewController.h"
#interface SearchViewController ()
#end
#implementation SearchViewController
#synthesize fooView = _fooView;
#end
I want the button touch event to be implemented in FooViewController, is delegate can achieve this? If YES, how?
Currently, I'm adding the touch event in such a way
FooViewController.m
- (void)viewDidLoad
{
[self.fooView.submitButton addTarget:self action:#selector(submitTapped:) forControlEvents:UIControlEventTouchUpInside];
}
...
- (IBAction)submitTapped
{
...
}
But I don't think this is a good solution, so need some expert advice.
Any idea?
Yes you can implement using delegate
FooView.h
#import <UIKit/UIKit.h>
#protocol FooViewDelegate
-(void)submitButtonClicked:(id)sender;
#end
#interface FooView : UIView
#property (nonatomic, strong) UITextField *barTextField;
#property (nonatomic, strong) UIButton *submitButton;
#property (nonatomic, assign) id<FooViewDelegate> delegate;
#end
FooView.m
#import "FooView.h"
#implementation FooView
#synthesize barTextField = _barTextField;
#synthesize submitButton = _submitButton;
#synthesize delegate;
...
-(IBAction)buttonClicked:(id)sender // connect this method with your button
{
[self.delegate submitButtonClicked:sender];
}
#end
FooViewController.h
#import <UIKit/UIKit.h>
#import "FooView.h"
#interface FooViewController : UIViewController <FooViewDelegate>
#property (nonatomic, strong) FooView *fooView;
#end
FooViewController.m
#import "FooViewController.h"
#interface FooViewController ()
#end
#implementation FooViewController
#synthesize fooView = _fooView;
- (void)viewDidLoad
{
_fooView = [[UIView alloc] init];
_fooView.delegate = self;
}
-(void)submitButtonClicked:(id)sender //delegate method implementation
{
NSLog(#"%#",[sender tag]);
}
#end