textFieldShouldReturn ignoring variables - ios

I have this code on my textFieldShouldReturn (is not in the same class as the method called):
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
LoginViewController *loginViewController = [[LoginViewController alloc]init];
if (textField.returnKeyType == UIReturnKeyJoin) [loginViewController logIn];
return (textField.returnKeyType == UIReturnKeyDone);
}
Everything works perfect until this point, this is the code of the "login" method:
- (IBAction)logIn{
NSString *username = [[self.usernameLoginField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] lowercaseString];
NSString *password = [[self.passwordLoginField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] lowercaseString];
NSLog(#"Username: %# - Password: %# ",username,password);
//Whatever
}
On my view, I have a button that calls that method, when I use that button the NSLog shows what the UITextField contains in that moment, otherwise, If the method is called from the "Join" (Return key) from de keyboard, the NSLog shows null content on the variables.
What am I missing?.

In my opinion you have 3 possible solutions:
Option 1: The best option IMHO.
You can use UIAlertView with UIAlertViewStyle = UIAlertViewStyleLoginAndPasswordInput
self.alertView = [[UIAlertView alloc] initWithTitle:nil
message:#"LogIn"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:#"Cancel", #"Join", nil];
self.alertView.alertViewStyle = UIAlertViewStyleLoginAndPasswordInput;
[self.alertView show];
Then with the delegate:
- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (alertView == self.alertView)
{
if (buttonIndex == 1)
{
[self logIn:[[alertView textFieldAtIndex:0] text] andPassword:[[alertView textFieldAtIndex:1] text]];
}
else if (buttonIndex == 0)
{
[self.navigationController popViewControllerAnimated:YES];
}
}
}
Remember to add: UIAlertViewDelegate
Option 2:
Working with [self performSegueWithIdentifier:#"identifier" sender:self] and
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
#pragma mark - UITextFieldDelegate
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.usernameLoginField)
{
[self.usernameLoginField resignFirstResponder];
[self.passwordLoginField becomeFirstResponder];
}
else if (textField == self.passwordLoginField)
{
[self.passwordLoginField resignFirstResponder];
//This Identifier is in the Storyboard
[self performSegueWithIdentifier:#"option2Segue" sender:self];
}
return true;
}
#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
{
[(YourViewController *)segue.destinationViewController setUsername:self.usernameLoginField.text];
[(YourViewController *)segue.destinationViewController setPassword:self.passwordLoginField.text];
}
In YourViewController.h you need:
#property (nonatomic, strong) NSString* username;
#property (nonatomic, strong) NSString* password;
Remember to add: UITextFieldDelegate
Option 3
To send back information, you should use Delegation:
In Your firstViewController.h:
#import "DelegateViewController.h"
#interface FirstViewController : UIViewController
(void) logIn: (NSString *) username password: (NSString *) password;
In Your firstViewController.m:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"option3Delegate"])
{
((DelegateViewController *) segue.destinationViewController).delegate = self;
}
}
In Your delegateViewController.h:
#protocol Option3Delegate <NSObject>
- (void) logIn: (NSString *) username password: (NSString *) password;
#end
#interface DelegateViewController : UIViewController
{
id myDelegate;
}
#property (nonatomic, assign) id<Option3Delegate> delegate;
#end
In Your delegateViewController.m:
#pragma mark - UITextFieldDelegate
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.usernameLoginField)
{
[self.usernameLoginField resignFirstResponder];
[self.passwordLoginField becomeFirstResponder];
}
else if (textField == self.passwordLoginField)
{
[self.passwordLoginField resignFirstResponder];
//This Identifier is in the Storyboard
if ([_delegate respondsToSelector:#selector(logIn:password:)])
{
[_delegate logIn:self.usernameLoginField.text password:self.passwordLoginField.text];
}
[self.navigationController popViewControllerAnimated:YES];
}
return true;
}
Remember to add: UITextFieldDelegate
Option 4: With KeyboardController
KeyboardController is a small solution to handle the Keyboard interaction inside UITextFields. However only handle with Next and Done Return keys. To handle the Join key you can do it in your ViewController. In the view controller where you allocate KeyboardController:
#property (strong, nonatomic) IBOutlet UITextField *usernameLoginField;
#property (strong, nonatomic) IBOutlet UITextField *passwordLoginField;
#property (strong, nonatomic) KeyboardController *keyboardController;
- (void)viewDidLoad
{
[super viewDidLoad];
id fields = #[self.usernameLoginField, self.passwordLoginField];
self.keyboardController = [KeyboardController controllerWithFields:fields];
//Important
self.passwordLoginField.delegate = self;
}
#pragma mark - UITextFieldDelegate
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.passwordLoginField)
{
[self.passwordLoginField resignFirstResponder];
[self logIn];
}
return true;
}
- (IBAction)logIn
{
NSLog(#"Username: %# - Password: %#", self.usernameLoginField.text, self.passwordLoginField.text);
//Whatever
}
You can download an example with the 4 options here:

Related

Expected identifier or '(' xcode error comming

There are two pages one for registration and other for login. username and password in login page should match with data in registration page. To do this i am using if-else statement for button that if data in registration page== login page username and password then go to next page on button click otherwise display error.
This is .h file
#import <UIKit/UIKit.h>
#interface ViewController2 : UIViewController<UITextFieldDelegate>
#property(strong,nonatomic)NSString *dataString;
#property (strong, nonatomic) IBOutlet UITextField *inputTxt1;
#property (strong, nonatomic) IBOutlet UITextField *inputTxt2;
#property (strong, nonatomic) IBOutlet UILabel *lblOutput;
- (IBAction)btnAction:(id)sender;
#end
this is .m file
#import "ViewController2.h"
#interface ViewController2 ()
{
int x;
}
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title=#"Login Id Page";
NSLog(#"Data String is %#",self.dataString);
_inputTxt1.delegate=self;
_inputTxt2.delegate=self;
_inputTxt1.returnKeyType=UIReturnKeyNext;
_inputTxt2.returnKeyType=UIReturnKeyDone;
if (_inputTxt1.text == self.dataString){
x=1;
}
else{
x=0;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.inputTxt1) {
[self.inputTxt2 becomeFirstResponder];
}
else if (textField == self.inputTxt2)
{
[textField resignFirstResponder];
}
return YES;
}
//error is comming right here at if statement:-
if (x==1)
{
- (IBAction)btnAction:(id)sender {
//navigation to next page
}
}
else
{
_lblOutput.text = #"wrong username or password";
}
#end
do like
//error is comming right here at if statement:-
if (x==1)
{
[self performseguewithIdentifier:#"xxxx"];
}
else
{
_lblOutput.text = #"wrong username or password";
}
choice-2
if (x==1)
{
[self btnAction:nil];
}
else
{
_lblOutput.text = #"wrong username or password";
}
cal method like
- (IBAction)btnAction:(id)sender {
//navigation to next page
[self performseguewithIdentifier:#"xxxx"];
// or do ur stuff here
}
first you define
- (IBAction)btnAction:(id)sender
{
//navigation to next page
}
then call it
if (x==1)
{
[self btnAction:nil]; //here
}

How to pass an object in a segue rather that a detail of an object?

I have a simple notes app where I have just 2 view controllers:
table view controller - to list all the notes.
view controller - to create new notes.
In the table view controller I have a segue from a cell back to the creation page where a user can edit the note in this specific cell.
But my problem is that when I'm preforming editing to a certain cell(note) I'm creating a new note with the content of what I edited...
So instead of passing the note content in the prepareForSegue method I need to pass the note object...
How can I do that?
this are my classes:
NMNote: (correctly just containing a property of *content, will add more behaviour later)
#import <Foundation/Foundation.h>
#interface NMNote : NSObject
#property (strong, nonatomic) NSString *content;
#end
NMCreateNotesViewController.h:
#import <UIKit/UIKit.h>
#import "NMNote.h"
#interface NMCreateNotesViewController : UIViewController
#property (strong, nonatomic) NMNote *note;
#property (weak, nonatomic) IBOutlet UITextView *textField;
#property (strong, nonatomic) NSString *passedInString;
#end
NMCreateNotesViewController.m:
#import "NMCreateNotesViewController.h"
#import "NMNotesListViewController.h"
#interface NMCreateNotesViewController () <UITextViewDelegate>
#property (weak, nonatomic) IBOutlet UIBarButtonItem *saveButton;
#end
#implementation NMCreateNotesViewController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// listen for keyboard hide/show notifications so we can properly adjust the table's height
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
#pragma mark - Notifications
- (void)adjustViewForKeyboardReveal:(BOOL)showKeyboard notificationInfo:(NSDictionary *)notificationInfo
{
// the keyboard is showing so ƒ the table's height
CGRect keyboardRect = [[notificationInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval animationDuration =
[[notificationInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.textField.frame;
// the keyboard rect's width and height are reversed in landscape
NSInteger adjustDelta = UIInterfaceOrientationIsPortrait(self.interfaceOrientation) ? CGRectGetHeight(keyboardRect) : CGRectGetWidth(keyboardRect);
if (showKeyboard)
frame.size.height -= adjustDelta;
else
frame.size.height += adjustDelta;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.textField.frame = frame;
[UIView commitAnimations];
}
- (void)keyboardWillShow:(NSNotification *)aNotification
{
[self adjustViewForKeyboardReveal:YES notificationInfo:[aNotification userInfo]];
}
- (void)keyboardWillHide:(NSNotification *)aNotification
{
[self adjustViewForKeyboardReveal:NO notificationInfo:[aNotification userInfo]];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (sender != self.saveButton) return;
if (self.textField.text.length > 0) {
self.note = [[NMNote alloc] init];
self.note.content = self.textField.text;
}
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if (self.passedInString != nil) {
self.textField.text = self.passedInString;
}
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
NMNotesListViewController.h:
#import <UIKit/UIKit.h>
#interface NMNotesListViewController : UITableViewController
- (IBAction) unwindToList: (UIStoryboardSegue *) segue;
#end
NMNotesListViewController.m:
#import "NMNotesListViewController.h"
#import "NMCreateNotesViewController.h"
#interface NMNotesListViewController ()
#property (strong, nonatomic) NSMutableArray *notes;
#end
#implementation NMNotesListViewController
- (IBAction) unwindToList: (UIStoryboardSegue *) segue
{
NMCreateNotesViewController *source = [segue sourceViewController];
NMNote *note = source.note;
if (note != nil) {
[self.notes addObject:note];
[self.tableView reloadData];
}
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.notes = [[NSMutableArray alloc] init];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#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 [self.notes count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"NotesPrototypeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NMNote *note = [self.notes objectAtIndex:indexPath.row];
cell.textLabel.text = note.content;
return cell;
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(UITableViewCell *)sender
{
if ([[segue identifier] isEqualToString:#"noteSegue"]) {
NMCreateNotesViewController *destination = [segue destinationViewController];
NSInteger indx = [self.tableView indexPathForCell:sender].row;
NMNote *note = self.notes[indx];
destination.passedInString = note.content;
}
}
//#pragma mark - delegate
//
//- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
//{
//
//}
#end
This is the screens flow:
the initiate view is this table view:
Now there is the TextView where you write the note:
Now, after you save a note, you go back to the first screen. and then you can tap on a populated cell and you will segue back to this screen (the one with the TextView) so you can edit it. But instead of editing it, it will create a new one with the edited content. like this:
Please, would appreciate any help here to accomplish my task..
Thanks!
The thing you need to do when you pass the note to the NMCreateNotesViewController, is to differentiate between an edit and an add action so when you came back to the table view, you can either replace the old entry with the new edited one, or add a new entry.
The way I would approach this is to have two segues, one from the + button (I'll call it "addSegue") and one from the table view cell (call it "editSegue"). I would also create a property in the list controller to hold the value of the edited row, or set it to something like -1 to indicate it's a new note. Something like this,
#property (nonatomic) NSInteger editedRow;
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"editSegue"]) {
NMCreateNotesViewController *destination = [segue destinationViewController];
NSInteger indx = [self.tableView indexPathForCell:(UITableViewCell *)sender].row;
self.editedRow = index;
NMNote *note = self.notes[indx];
destination.note = note;
}else if ([segue.identifier isEqualToString:#"addSegue"]) {
self.editedRow = -1;
}
The prepareForSegue method in the NMCreateNotesViewController would be the same as you have in your question. You can get rid of the passedInString property since we're passing in the entire note object instead. In the unwind method in the list controller, you would do this,
- (IBAction) unwindToList: (UIStoryboardSegue *) segue {
NMCreateNotesViewController *source = [segue sourceViewController];
NMNote *note = source.note;
if (note != nil && self.editedRow == -1) {
[self.notes addObject:note];
}else{
[self.notes replaceObjectAtIndex:self.editedRow withObject:note];
}
[self.tableView reloadData];
}
in NMCreateNotesViewController.h:
#property (strong, nonatomic) NMNote *note;
#property BOOL adding;
#property (strong,nonatomic) NSString *originalContent;
Then in your NMNotesListViewController.m prepareForSegue
destination.note=self.notes[indx];
destination.adding=NO; // set adding to yes if you are adding a new note
and in your unwind
- (IBAction) unwindToList: (UIStoryboardSegue *) segue
{
NMCreateNotesViewController *source = [segue sourceViewController];
NMNote *note = source.note;
if (source.adding && note != nil) {
[self.notes addObject:note];
[self.tableView reloadData];
}
}
in NMCreateNotesViewController.m
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// listen for keyboard hide/show notifications so we can properly adjust the table's height
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
if (self.note != nil)
{
self.originalContent=self.note.content;
self.textField.text=self.note.content;
}
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (sender != self.saveButton)
{
if (self.note != nil)
{
self.note.content=self.originalContent;
}
}
else
{
if (self.note == nil)
{
if (self.textField.text.length > 0) {
self.note = [[NMNote alloc] init];
}
self.note.content = self.textField.text;
}
}

UIScrollView not responding to touch

My UIScrollView is not responding to touch events, nor is my touchesBegain method being called for my UIViewController. (Also the text on my buttons are distorted on one and not shown on the other)
In Storyboard I added the ScrollView to the UIViewController and added my UITextFields and UIButtons to the ScrollView
Here is the code:
#import <UIKit/UIKit.h>
#interface RefineSearchViewController : UIViewController <UITextFieldDelegate, UIScrollViewDelegate>
{
IBOutlet UIScrollView *scroller;
}
#property (strong, nonatomic) IBOutlet UITextField *nameField;
#property (strong, nonatomic) IBOutlet UITextField *targetField;
#property (strong, nonatomic) IBOutlet UITextField *vendorField;
#property (strong, nonatomic) IBOutlet UITextField *CATField;
#property (strong, nonatomic) IBOutlet UITextField *clonalityField;
#property (strong, nonatomic) IBOutlet UITextField *sourceOrganismField;
-(IBAction) textFieldReturn: (id) sender;
#import "RefineSearchViewController.h"
#import "DBHandler.h"
#interface RefineSearchViewController ()
#end
#implementation RefineSearchViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[scroller setScrollEnabled:YES];
// set the content size to be the size our our whole frame
//scroller.frame = CGRectMake(74, 261, 620, 354);
[scroller setContentSize:CGSizeMake(2000, 2000)];
[scroller setCanCancelContentTouches:NO];
[super viewDidLoad];
// Do any additional setup after loading the view.
self.targetField.delegate = self;
self.nameField.delegate = self;
self.vendorField.delegate = self;
self.clonalityField.delegate = self;
self.sourceOrganismField.delegate = self;
self.CATField.delegate = self;
}
-(void) viewWillAppear:(BOOL)animated
{
self.navigationController.navigationBarHidden = YES;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// If you are going to conduct a refine search
if ([[segue identifier] isEqualToString:#"Refine"])
{
DBHandler *handler = [[DBHandler alloc]init];
//Run searches on each of the parameter that aren't empty
NSString *nameParameter = _nameField.text;
if (![nameParameter isEqualToString:#""])
{
[handler search:0 andInput:nameParameter];
}
NSString *targetParameter = _targetField.text;
if(![targetParameter isEqualToString:#""])
{
[handler search:1 andInput:targetParameter];
}
NSString *vendorParameter = _vendorField.text;
if (![vendorParameter isEqualToString:#""])
{
[handler search:2 andInput:vendorParameter];
}
NSString *catParameter = _CATField.text;
if (![catParameter isEqualToString:#""])
{
[handler search:3 andInput:catParameter];
}
NSString *clonalityField = _clonalityField.text;
if (![catParameter isEqualToString:#""])
{
[handler search:4 andInput:clonalityField];
}
NSString *sourceField = _sourceOrganismField.text;
if (![sourceField isEqualToString:#""])
{
[handler search:5 andInput:sourceField];
}
//recursive implementation
for (int i = 0; i < 6 ; i++)
{
}
//We shouldn't clear the text fields here in my personal opinion because they apply to the search until you return to the homescreen and reset what is the
//current "working database"
}
//if you are going to cancel the refine search, simply go back to the previous screen
else if ([[segue identifier] isEqualToString:#"Cancel"])
{
//Do Nothing
//but more importantly....
//....clear Text Fields
_nameField.text = #"";
_targetField.text = #"";
_vendorField.text = #"";
_CATField.text = #"";
_clonalityField.text = #"";
_sourceOrganismField.text = #"";
}
}
//make that stubborn keyboard go away whenever you touch the background
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[_nameField resignFirstResponder];
[_targetField resignFirstResponder];
[_vendorField resignFirstResponder];
[_CATField resignFirstResponder];
[_clonalityField resignFirstResponder];
[_sourceOrganismField resignFirstResponder];
}
-(IBAction)textFieldReturn:(id)sender
{
[sender resignFirstResponder];
}
//following code was taken and tweaked from stack overflow
//- (void)textFieldDidBeginEditing:(UITextField *)textField
//{
// [self animateTextField: textField up: YES];
// NSLog(#"YO");
//}
//
//
//- (void)textFieldDidEndEditing:(UITextField *)textField
//{
// [self animateTextField: textField up: NO];
//}
//
//- (void) animateTextField: (UITextField*) textField up: (BOOL) up
//{
// const int movementDistance = 216; //height of the keyboard
// const float movementDuration = 0.3f; // duration of the animation
//
// int movement = (up ? -movementDistance : movementDistance);
//
// [UIView beginAnimations: #"anim" context: nil];
// [UIView setAnimationBeginsFromCurrentState: YES];
// [UIView setAnimationDuration: movementDuration];
// self.view.frame = CGRectOffset(self.view.frame, 0, movement);
// [UIView commitAnimations];
//}
#end
Make sure your scrollView's delegate is set properly in storyboard and scrollView's userInteractionEnabled is set.

methods from a protocol is not called

I got the next problem I have 3 views (a UITableView, and2 View Controller) I made the next 2 protocols : AddViewControllerDelegate and ViewAlarmControllerDelegate:
AddViewController.h :
#protocol AddViewControllerDelegate <NSObject>
- (void)addAlarm:(AlarmObject *)alarm;
#end
#interface AddViewController : UIViewController
{
id <AddViewControllerDelegate> delegate;
}
#property (retain) id delegate;
ViewAlarmController.h:
#protocol ViewAlarmControllerDelegate <NSObject>
- (void)changeAlarm:(AlarmObject *)alarm atIndex:(int) alarmID;
- (void)deleteAlarmAtIndex:(int) alarmID;
#end
#interface ViewAlarmController : UIViewController
{
id <ViewAlarmControllerDelegate> delegate;
}
#property (retain) id delegate;
Then in HomeViewController.h I imported as fallow:
#import "AddViewController.h"
#import "ViewAlarmController.h"
#import "AlarmObject.h"
#interface HomeViewController : UITableViewController <AddViewControllerDelegate, ViewAlarmControllerDelegate>
And I have the next declaration of methods into HomeViewController.m
- (void)addAlarm:(AlarmObject *)alarm{
[self.items addObject:alarm];
[self.tableView reloadData];
NSLog (#"added");
}
- (void)deleteAlarmAtIndex:(int)alarmID{
NSLog(#"alarmID: %d", alarmID);
[self.items removeObjectAtIndex:alarmID];
NSLog(#"items: %#", items);
[self.tableView reloadData];
}
- (void)changeAlarm:(AlarmObject *)alarm atIndex:(int)alarmID{
NSLog(#"change");
}
ViewAlarmController.m the calling of protocol's method code block:
- (IBAction)save:(id)sender {
AlarmObject* alarmObj = [[AlarmObject alloc]init];
if(![self.alarmNameField.text isEqual: #""]){
[alarmObj setValue:self.alarmNameField.text forKey:#"alarmName"];
NSLog (#"change alarm id = %d", alarmID);
[self.delegate changeAlarm:alarmObj atIndex:alarmID];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)reverse:(id)sender {
alarmNameField.text = [alarm valueForKey:#"alarmName"];
}
- (IBAction)deleteAlarm:(id)sender {
NSLog (#"delete alarm id: %d",alarmID);
[self.delegate deleteAlarmAtIndex:alarmID];
[self dismissViewControllerAnimated:YES completion:nil];
}
The problem is that the addAlarm works but when i go into ViewAlarm and i press the button to delete or save the changes the deleteAlarmAtIndex and changeAlarm methods are not called.
The problem was in the next method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"addAlarmSegue"]){
AddViewController *avc = segue.destinationViewController;
avc.delegate = self;
}else if ([segue.identifier isEqualToString:#"viewAlarmSegue"]){
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
ViewAlarmController *vac = segue.destinationViewController;
[vac getObject:[self.items objectAtIndex:selectedRowIndex.row] withId:selectedRowIndex.row];
vac.delegate = self;
}
}
I didn't wrote vac.delegate = self;
Make sure that object which should conforms to your protocol is not nil
My1Object *a = [My1Object new];
My2Object <Myprotocol> *b = [My2Object new];
a.delegate = b;
#interface My1Object <MyProtocol>
#property (nonatomic, weak /* or 'unsafe_unretained' for iOS less than 5.0*/) id <MyProtocol> delegate;
#end
#implementation My1Object
...
- (void)somethingHappened {
// just for check as I said:
NSLog(#"self.delegate = %#", self.delegate); // make sure this is not nil!
if ([self.delegate respondsToSelector:#selector(myProtocolMethod:)]) {
[self.delegate myProtocolMethod:self];
}
}
...
#end
Remember that you shouldn't retain (strong) your delegate!

How to position a popover depending on which segment (UISegmentedControl) has been selected

I have programmatically created a custom cell of a dynamic table by integrating a segmentedcontrol of 8 segments.
It works well but once I tap on one of the segments, I would like that a popup menu with options appears near the cell and not at the lower end of the tableview.
I suppose that this occurrs because I have anchored the segue to the tableview. I would like to avoid to assign to each segment a segue to the popup menu.
Is there any possibility of re-positioning the popup menu automatically depending on the segment selected?
Here is the relevant code at the main view controller .m file
-(void)segmentSelectedAtRow: (UISegmentedControl *)sender{
if (self.flipsidePopoverController) {
[self.flipsidePopoverController dismissPopoverAnimated:YES];
self.flipsidePopoverController = nil;
} else {
[self performSegueWithIdentifier:#"segueToChangeValues" sender:sender];
}
UITableViewCell *theParentCell = [[sender superview]superview];
NSIndexPath *indexPathOfSegment = [self.spreadSheetView indexPathForCell:theParentCell];
...
}
...
- (void)flipsideViewControllerDidFinish:(POTFlipsideViewController *)controller {
[self.flipsidePopoverController dismissPopoverAnimated:YES];
self.flipsidePopoverController = nil;
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
self.flipsidePopoverController = nil;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"segueToChangeValues"]) {
[[segue destinationViewController] setDelegate:self];
UIPopoverController *popoverController = [(UIStoryboardPopoverSegue *)segue popoverController];
self.flipsidePopoverController = popoverController;
popoverController.delegate = self;
}
}
#end
here is the flipside .h file
#class POTFlipsideViewController;
#protocol POTFlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(POTFlipsideViewController *)controller;
#end
#interface POTFlipsideViewController : UIViewController
#property (weak, nonatomic) id <POTFlipsideViewControllerDelegate> delegate;
- (IBAction)done:(id)sender;
....
#end
here is the relevant code for the flipside .m file
#import "POTFlipsideViewController.h"
#interface POTFlipsideViewController ()
#end
#implementation POTFlipsideViewController
- (void)awakeFromNib
{
self.contentSizeForViewInPopover = CGSizeMake(320.0, 480.0);
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
return YES;
}
- (IBAction)done:(id)sender
{
[self.delegate flipsideViewControllerDidFinish:self];
}
#end

Resources