Delegate Not Working - objective-c

I'm Trying to dismiss a popover and transfer data at the same time. I implemented a delegate DismissPopoverDelegate but it is failing to work. But there are no errors. If the save button is tapped it registers it and it completes the line after where it calls the delegate. But its not working...
AddEventViewController_iPad.h
#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#import <EventKit/EventKit.h>
#import <EventKitUI/EventKitUI.h>
#import <MessageUI/MessageUI.h>
#import <MessageUI/MFMailComposeViewController.h>
#import <Foundation/Foundation.h>
#import "AboutSme.h"
#import "dateViewPopOverViewController_iPad.h"
#import "addPersonViewControllerPopover_iPad.h"
#import "PreviousEventsTableViewControllerPopover_iPad.h"
#interface AddEventViewController_iPad : UIViewController <UITableViewDelegate, UITableViewDataSource, MFMailComposeViewControllerDelegate, UITextFieldDelegate, UIAlertViewDelegate,UIPopoverControllerDelegate,UINavigationControllerDelegate,UIPopoverControllerDelegate,ABPeoplePickerNavigationControllerDelegate, ABNewPersonViewControllerDelegate, DismissPopoverDelegate> {
UIPopoverController *pop;
AddEventViewController_iPad.m
- (IBAction) selectStartDate:(id) sender {
NSLog(#"Select start date");
dateViewPopOverViewController_iPad *dateViewPopOverViewController = [[dateViewPopOverViewController_iPad alloc] init];
popover2 = [[UIPopoverController alloc] initWithContentViewController:dateViewPopOverViewController];
popover2.delegate = self;
popover2.popoverContentSize = CGSizeMake(320, 460);
CGRect rect = CGRectMake(790, 170, 175, 300);
[popover2 presentPopoverFromRect:rect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionRight animated:YES];
[dateViewPopOverViewController release];
/*
if (dateViewController == nil) {
dateViewController = [[DateViewController_iPad alloc] initWithNibName:#"DateViewController_iPad" bundle:nil];
}
[self presentModalViewController:dateViewController animated:YES];
[dateViewController retain];
*/
}
- (void) dismissWithData:(NSString *)data
{
NSLog(#"%#", data);
[pop dismissPopoverAnimated:YES];
[pop release];
}
dateViewPopOverViewController_iPad.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#protocol DismissPopoverDelegate <NSObject>
#required
- (void) dismissWithData:(NSString *)data;
#end
#interface dateViewPopOverViewController_iPad : UIViewController {
IBOutlet UIDatePicker *datePicker;
IBOutlet UISegmentedControl *segmentedBar;
IBOutlet UILabel *startLabel;
IBOutlet UILabel *endLabel;
IBOutlet UISwitch *allDaySwitch;
NSDate *startDate;
NSDate *endDate;
NSDate *now;
NSDateFormatter *dateFormatter;
id<DismissPopoverDelegate> delegate;
}
#property (retain) id delegate;
- (void) dismissWithData:(NSString *)data;
dateViewPopOverViewController_iPad.m
#implementation dateViewPopOverViewController_iPad
#synthesize startDate, endDate, datePicker, segmentedBar, startLabel, endLabel, now, allDaySwitch, delegate;
- (IBAction) save:(id)sender {
if ([self startDateIsValid] && [self endDateIsValid]) {
//[[self parentViewController] setDatesForEvent:startDate eventEndDate:endDate allDay:[allDaySwitch isOn]];
// [self dismissModalViewControllerAnimated:YES];
NSLog(#"works");
[self.delegate dismissWithData:#"Some text from popover"];
NSLog(#"works1");
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Ooops!" message:#"Please check the dates! Remember the end date must occur after the start date for the event to save." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
}

You have a circular reference when including the .h files.
dateViewPopOverViewController_iPad.h includes AddEventViewController_iPad.h and AddEventViewController_iPad.h includes dateViewPopOverViewController_iPad.h, which will cause the compiler to raise an error.
One of the aims to use protocols is to avoid this kind of circular reference. Removing the dateViewPopOverViewController_iPad.h include from your AddEventViewController_iPad.h file might fix the problem

Your call to dismissPopoverAnimated will not trigger the call to the delegate. From Apple's UIPopoverDelegate documentation:
The popover controller does not call this method in response to programmatic calls to the dismissPopoverAnimated method. If you dismiss the popover programmatically, you should perform any cleanup actions immediately after calling the dismissPopoverAnimated method.

Related

how to give action to UIButtoun Outlet from another UIViewController

I have two UIViewController class with names : (RootViewController & SecondViewController).
I have one UIButton Outlet in my SecondViewController.now I want give action method to my UIButton in RootViewController.but I don't know about it.
please guide me and tell me how to get my UIButton in another View and give action method on it in another View....
I'm not sure why you are doing this, it doesn't look good.
Anyway, here's the way.
SecondViewController.h
#interface SecondViewcontroller:UIViewController
#property (nonatomic, weak) IBOutlet UIButton *theButton;
#end
RootViewController.m
SecondViewContoller * sv = [[SecondViewController alloc] init];
[sv.theButton addTarget:self action:#selector(buttonHandler:) forControlEvents:UIControlEventTouchUpInside];
You have to removeTarget when you've done with the button.
Why don't you use delegate or block callback?
ADDED
delegate
SecondViewController.h
#protocol SecondViewControllerDelegate <NSObject>
- (void)theButtonPressed;
#end
#interface SecondViewController : UIViewController
#property (nonatomic, strong) id<SecondViewControllerDelegate>delegate;
#end
SecondViewController.m
#interface SecondViewController ()
{
UIButton *theButton;
}
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[theButton addTarget:self.delegate action:#selector(theButtonPressed) forControlEvents:UIControlEventTouchUpInside];
}
#end
RootViewcontroller.h
#interface RootViewController : UIViewController <SecondViewControllerDelegate>
#end
RootViewController.m
SecondViewController *sv = [[SecondViewController alloc] init];
[sv setDelegate:self];
and
- (void)theButtonPressed
{
}
block
SecondViewController.h
typedef void(^TheButtonTouched)(void);
#interface SecondViewController : UIViewController
- (void)addButtonEvent:(TheButtonTouched)event;
#end
SecondViewController.m
#interface SecondViewController ()
{
UIButton *theButton;
TheButtonTouched buttonBlock;
}
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// button alloc init here and..
[theButton addTarget:self action:#selector(buttonEvent:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonEvent:(UIButton *)sender
{
if(buttonBlock)
{
buttonBlock();
}
}
- (void)addButtonEvent:(TheButtonTouched)event
{
buttonBlock = event;
}
#end
RootViewController.m
SecondViewController *sv = [[SecondViewController alloc] init];
[sv addButtonEvent:^{
// ADD SOMTHING HERE
}];
You need to create the button's iboutlet property.
Than using object of secondclass.button name you can assign selector.
[classobjectname..btnname addTarget:objectname.class action:#selector(objectname.methodname:);
Just Create RootViewController 's Object and passed into target parameter.
e.g.
[btnShow addTarget:self.rootCtrlObj action:#selector(viewPhoto_click:)
forControlEvents:UIControlEventTouchUpInside];
where rootCtrlObj is #property inside SecondViewController.h file
and when you push this controller in RootViewController you have to pass reference of RootViewController .
For Example,
secVCObj.rootCtrlObj = self;
[self.navigationController pushViewController:secVCObj animated:YES];
as i said custom delegate methods will work perfect for these cases,
in SecondViewController.h file define a custom delegate method like below
#import <UIKit/UIKit.h>
#import "ViewController.h"
#protocol SecondControllerDelegate<NSObject>
- (void)someActionToPerformInRootController;
#end
#interface SecondViewController : UIViewController
#property (nonatomic, assign) id<SecondControllerDelegate>delegate; //declare a custom delegate
#end
in SecondViewController.m file lets take an action of some button
- (IBAction)myButtonActionMethod:(id)sender
{
if([self.delegate respondsToSelector:#selector(someActionToPerformInRootController)])
{
[self.delegate someActionToPerformInRootController]; //this will call the delegate method in first view conroller( root view controller) //do what ever u want t do in the action method of rootviewcontroller
}
}
in RootViewController.h file
#import "SecondViewController.h"
#interface RootViewController : UIViewController < SecondControllerDelegate> //confirmas to delegate
in RootViewController.m while presenting the SecondViewController set the delegate to self
- (IBAction)showAction:(id)sender
{
SecondViewController *secondController = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
secondController.delegate = self; //call back to this controller
[self presentViewController:secondController animated:YES completion:nil];
}
//this method called from the secondViewcontroller
- (void) someActionToPerformInRootController
{
NSLog(#"perform action in root view controller");
}

Incomplete Implementation Errror

Keep getting a error on the last line #implementation line saying implementation incomplete. Not sure what the problem is. What would cause this? I posted the header too.
Added the rest of the code from the .m file.
#import "mmViewController.h"
#interface mmViewController ()
-(void)timerFired:(NSTimer*)theTimer;
#end
#implementation mmViewController
#synthesize remainingTime, playerScore, scrambledWord;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)viewDidLoad
{
[super viewDidLoad];
//Do any additional setup after loading the view, typically from a nib.
//Initialize the game model
gameModel = [[mmScramblerModel alloc] init];
//Display the time, score and scrambled word
remainingTime.text = [NSString stringWithFormat:#"%i", gameModel.time];
playerScore.text = [NSString stringWithFormat:#"%i", gameModel.score];
scrambledWord.text = [gameModel getScrambledWord];
//Start the game timer
gameTimer = [NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:#selector(timerFired:)
userInfo:nil
repeats:YES];
}
-(void) endGameWithMessage:(NSString *)message {
//Call this method to end the game
//Invalidate the timer
[gameTimer invalidate];
//Show an alert with the results
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Game Over!"
message:message
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
-(void) timerFired:(NSTimer *)theTimer {
//The timer fires this method rougly every second
[gameModel timerTick];
if(gameModel.time <= 0){
remainingTime.text = 0;
[self endGameWithMessage:#"You are out of time. You lose!"];
}
else
remainingTime.text = [NSString stringWithFormat:#"%i", gameModel.time];
}
#end
#import <UIKit/UIKit.h>
#import "mmScramblerModel.h"
#interface mmViewController : UIViewController {
mmScramblerModel* gameModel;
NSTimer* gameTimer;
}
-(IBAction)guessTap:(id)sender;
-(void) endGameWithMessage:(NSString*) message;
#property (weak, nonatomic) IBOutlet UITextField * guessText;
#property (weak, nonatomic) IBOutlet UILabel * scrambledWord;
#property (weak, nonatomic) IBOutlet UILabel * remainingTime;
#property (weak, nonatomic) IBOutlet UILabel * playerScore;
#end
Look at the methods listed in the .h file. Now look at the methods that you actually implemented. SInce there are only two, it's pretty easy to notice that you didn't implement one of them.
Implement the guessTap: method.
From your code i can see the interface declaration of
-(IBAction)guessTap:(id)sender;
But you have not implemented this method in .m file
remove the guessTap: method from interface

UIAlertViewDelegate in separate class crashes application

I'm having difficulties with UIAlertView delegation in class other than ViewController.
Everything is fine until user clicks the OK button - then app crashes with
Thread 1: EXC_BAD_ACCESS (code=2, address 0x8)
ViewController.h:
#import <UIKit/UIKit.h>
#import "DataModel.h"
#interface ViewController : UIViewController
#end
ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
DataModel *dataModel = [[DataModel alloc] init];
[dataModel ShowMeAlert];
[super viewDidLoad];
}
#end
DataModel.h
#import <Foundation/Foundation.h>
#interface DataModel : NSObject <UIAlertViewDelegate>
- (void)ShowMeAlert;
#end
DataModel.m
#import "DataModel.h"
#implementation DataModel
- (void)ShowMeAlert;
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Info" message:#"View did load!" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
#pragma mark - UIAlertView protocol
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
NSLog(#"Index: %d", buttonIndex);
}
#end
If code for showing alert and it's delegation methods is in ViewController - works perfectly.
When I remove UIAlertDelegation method ...didDismissWithButtonIndex... -
works without delegation.
When I set UIAlertView delegate to nil -
works without delegation.
Any clues what's wrong?
In this method:
- (void)viewDidLoad
{
DataModel *dataModel = [[DataModel alloc] init];
[dataModel ShowMeAlert];
[super viewDidLoad];
}
you are allocating a DataModel local variable which will be deallocated by ARC at the end of the scope. Hence, when dismiss is executed, your delegate is not there anymore. The fix for this is to store your DataModel in a strong property of your view controller. This way it will not be deallocated. The you would do:
- (void)viewDidLoad
{
self.dataModel = [[DataModel alloc] init];
[self.dataModel ShowMeAlert];
[super viewDidLoad];
}

delegate gets null when performWithSegue

Im trying to send some info from a modal view to a delgate. But it seems like my delegate doesnt follow through, it gets null. It looks like this in IB http://i.imgur.com/7oaxb.png.
But it works if i remove the navigationController that is right before the modal view and use the buttons in the View.
please help, ive tried for like 5 hours... :/
Heres the modalViewController code:
#import
#import "Link.h"
#protocol modalViewDelegate <NSObject>
-(void)closeview;
-(void)saveLink:(Link *)link;
#end
#interface modelViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *titel;
#property (weak, nonatomic) IBOutlet UITextField *url;
#property (nonatomic, weak) id <modalViewDelegate> delegate;
- (IBAction)exitModal:(id)sender;
- (IBAction)saveLink:(id)sender;
#end
and .m:
#import "modelViewController.h"
#interface modelViewController ()
#end
#implementation modelViewController
#synthesize titel;
#synthesize url, delegate;
- (IBAction)exitModal:(id)sender {
//[self.delegate closeview];
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)saveLink:(id)sender {
if (titel.text.length > 0 && url.text.length > 0) {
NSString *urlen = [NSString stringWithFormat:#"%#", url.text];
Link *linken = [[Link alloc] initWithURL:[NSURL URLWithString:urlen]];
linken.title = titel.text;
NSLog(#"%#", delegate); **//returns null when pressing button** it returns null if i put it in viewDidLoad to..
[self.delegate saveLink:linken];
[self dismissModalViewControllerAnimated:YES];
} else {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:#"warning" delegate:self cancelButtonTitle:#"ok" otherButtonTitles:nil, nil];
[alertView show];
}
}
#end
the MasterViewController .h (that pushes the modalview:
#import <UIKit/UIKit.h>
#import "modelViewController.h"
#class DetailViewController;
#interface MasterViewController : UITableViewController <modalViewDelegate>
....
and .m
#import "MasterViewController.h"
#import "DetailViewController.h"
#implementation MasterViewController
#synthesize detailViewController = _detailViewController;
#synthesize links;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"linkPush"]) {
// Skicka länken till detaljvyn
DetailViewController *detailVC = segue.destinationViewController;
detailVC.link = [self.links objectAtIndex:self.tableView.indexPathForSelectedRow.row];
NSLog(#"%#", detailVC);
}
//this is the modalview "pusher"
if ([segue.identifier isEqualToString:#"newLink"]) {
modelViewController *mvc = segue.destinationViewController;
mvc.delegate = self;
NSLog(#"%#", mvc.delegate);
}
}
- (void)closeview {
[self dismissModalViewControllerAnimated:YES];
//[self.tabBarController dismissModalViewControllerAnimated:YES];
}
-(void)saveLink:(Link *)link{
NSLog(#"hello");
[links insertObject:link atIndex:links.count]; //updates a Tableview and works fine if delegate is called
[self.tableView reloadData];
//[self dismissModalViewControllerAnimated:YES];
}
If your destination view controller is wrapped into a navigation controller, you have to refer to it differently in prepareForSegue:
UINavigationController *nav = segue.destinationViewController;
DetailViewController *dvc = [nav.viewControllers objectAtIndex:0];
Now setting the properties, including the delegate, should work.

UIPopoverController Delegate Problem?

I have a UIPopover that I want to use either
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{
return NO;
}
or
-(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController{}
on. Neither of them seem to work (and I'm sure once one is fixed, the other will be too since it's probably a problem with delegates). For delegates, here is what I have:
In optionsViewController.h, the view which is inside the popover:
#import <UIKit/UIKit.h>
#protocol OptionsViewControllerDelegate <NSObject>
-(void)didPick:(NSString *)string;
#end
id delegate;
#interface OptionsViewController : UIViewController <OptionsViewControllerDelegate>{
IBOutlet UIPickerView *picker;
NSMutableArray *list;
}
#property (nonatomic, copy) NSArray *passthroughViews;
#property(nonatomic,retain) NSMutableArray *list;
#property(nonatomic,assign) id<OptionsViewControllerDelegate> delegate;
#end
and in the .m:
#synthesize delegate;
and in the .h of the view where the popover appears:
#interface exampleViewController : UIViewController <OptionsViewControllerDelegate,UIPopoverControllerDelegate>{
UIPopoverController *popoverController;
OptionsViewController *optionsViewController;
}
and in the .m:
#synthesize popoverController;
#synthesize optionsViewController;
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{
return NO;
}
[popoverController release];
[optionsViewController release];
In the ViewDidLoad, I have:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
optionsViewController =[[OptionsViewController alloc]init];
optionsViewController.delegate = self;
popoverController = [[UIPopoverController alloc] initWithContentViewController:optionsViewController];
popoverController.popoverContentSize = CGSizeMake(320, 216);
}
To present the popover, I use:
-(IBAction)showDecadePopover{
[popoverController presentPopoverFromRect:CGRectMake(150, 50, 150, 50) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
I'm probably missing something really obvious (that's why I gave so much of my code). Thanks so much!
Luke
Yep, simple fix. After you init the popoverController you need to set the exampleViewController as the delegate of it.
[popoverController setDelegate:self];
PS: What is the id delegate; floating after your OptionsViewControllerDelegate protocol definition for? Synthesizing delegate, which you already do, is all you need to create storage for it.