Xcode thinks delegate method is actually a new method being declared - ios

I just created a new utility application from the Xcode templates and I have a problem with the - (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller method not being called. When I use the three finger tap on the trackpad to define it, it says that method is defined in MainViewController.m when it is definitely in the protocol of Flip.
MainVC.h
#import "FlipsideViewController.h"
#interface MainViewController : UIViewController <FlipsideViewControllerDelegate, UIPopoverControllerDelegate>
#property (strong, nonatomic) UIPopoverController *flipsidePopoverController;
#property (weak, nonatomic) IBOutlet UIView *backgroundView;
#end
.m
#import "MainViewController.h"
#interface MainViewController ()
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_backgroundView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"Background.jpg"]];
_backgroundView.contentMode = UIViewContentModeCenter;
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Flipside View Controller
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller
{
//width
if (controller.widthSegmentedControl.selectedSegmentIndex == 0) {
//number of icons
} else {
//icon space
}
NSLog(#"b"); // not called
[self.flipsidePopoverController dismissPopoverAnimated:YES];
}
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
self.flipsidePopoverController = nil;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showAlternate"]) {
[[segue destinationViewController] setDelegate:self];
UIPopoverController *popoverController = [(UIStoryboardPopoverSegue *)segue popoverController];
self.flipsidePopoverController = popoverController;
self.flipsidePopoverController.delegate = self;
}
}
- (IBAction)togglePopover:(id)sender
{
if (self.flipsidePopoverController) {
[self.flipsidePopoverController dismissPopoverAnimated:YES];
self.flipsidePopoverController = nil;
} else {
[self performSegueWithIdentifier:#"showAlternate" sender:sender];
}
}
#end
FlipVC.h
#import <UIKit/UIKit.h>
#class FlipsideViewController;
#protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
#end
#interface FlipsideViewController : UIViewController
#property (weak, nonatomic) IBOutlet UISegmentedControl *widthSegmentedControl;
#property (weak, nonatomic) IBOutlet UITextField *widthNumberOfIcons;
#property (weak, nonatomic) IBOutlet UITextField *widthIconSpace;
#property (weak, nonatomic) IBOutlet UISegmentedControl *heightSegmentedControl;
#property (weak, nonatomic) IBOutlet UITextField *heightNumberOfIcons;
#property (weak, nonatomic) IBOutlet UITextField *heightIconSpace;
#property (weak, nonatomic) id <FlipsideViewControllerDelegate> delegate;
- (IBAction)done:(id)sender;
#end
.m
#import "FlipsideViewController.h"
#interface FlipsideViewController ()
#end
#implementation FlipsideViewController
- (void)awakeFromNib
{
self.preferredContentSize = CGSizeMake(320.0, 480.0);
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Actions
- (IBAction)done:(id)sender
{
NSLog(#"a"); //this is called
[self.delegate flipsideViewControllerDidFinish:self];
}
#end
There are two NSLogs in there, one for the method where the done button gets pressed (a) and one for the one where that didFinish method should be called (b). The problem is that when I press the done button on the Flip controller nothing happens (although "a" gets logged).

I found the problem. I removed the default button bar Info item and replace it with a normal button. The problem is that the segue needs to be anchored to that button and connected to the togglePopover method in the MainViewController.m file.

Related

How to change Xib's label from UIViewController

I have Xib UIView which is being displayed by my ViewController. The Xib contains an UILabel and an UIButton. My button coats all over my xib and i'm using it to navigate my SecondViewController and i achieve this by delegate methods.
Here's the thing about my label; because my button is transparent, i can show it beneath the button. What i can't do is to change mylabel's text from ViewController.
I did some search and come across a suggestion like this:
is create another .nib file for the subview and put the subview in
there. Then in that .nib file, make the file owner IOSubview. Property
connections will work just fine there. Then just add the subview to
your IOViewController programatically. Just remember to load the nib
file from bundle first.
link : https://stackoverflow.com/a/20294118/1450201
But it doesn't make sense to me because the reason i created the xib at first is to use it more than once. I believe solution to this problem could be much simpler. But how??
This is what my xib looks like:
And here is a github repo link and my code:
https://github.com/TimurAykutYildirim/demoView
ViewController.h
#import <UIKit/UIKit.h>
#import "Mini.h"
#interface ViewController : UIViewController <SelectionProtocol>
#property (weak, nonatomic) IBOutlet Mini *miniView;
#property (weak, nonatomic) IBOutlet UILabel *miniLabel;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.miniView.delegate = self;
}
-(void) isClicked {
NSString * storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
[self presentViewController:vc animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Mini.h
#import <UIKit/UIKit.h>
#protocol SelectionProtocol;
#interface Mini : UIView
#property (nonatomic, weak) id<SelectionProtocol> delegate;
- (IBAction)btnClick:(id)sender;
#end
#protocol SelectionProtocol <NSObject>
#required
-(void) isClicked;
#end
Mini.m
#import "Mini.h"
#implementation Mini
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self load];
}
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[self load];
}
return self;
}
- (void)load {
UIView *view = [[[NSBundle bundleForClass:[self class]] loadNibNamed:#"Mini" owner:self options:nil] firstObject];
[self addSubview:view];
view.frame = self.bounds;
// ui component properties will be set here
}
- (IBAction)btnClick:(id)sender {
if ([self.delegate conformsToProtocol:#protocol(SelectionProtocol)]) {
[self.delegate isClicked];
}
}
#end
Update your Mini.h to add label outlet to it.
Mini.h
#import <UIKit/UIKit.h>
#protocol SelectionProtocol;
#interface Mini : UIView
#property (nonatomic, weak) id<SelectionProtocol> delegate;
#property (weak, nonatomic) IBOutlet UILabel *miniLabel;
- (IBAction)btnClick:(id)sender;
#end
#protocol SelectionProtocol <NSObject>
#required
-(void) isClicked;
#end
and in ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.miniView.delegate = self;
self.miniView.miniLabel.text = //set whatever value
}

Delegate not responds to selector

Basically, I am now intend to use delegate to pass values between view controllers.
The flow of the view controllers is A -> B -> C using push segue.
When the user does some action in the "C" view controller, how to pass the value BACK to the first view controller, which is "A"?
In my code, "self.delegate" is always nil and the delegate method is never triggered.
Below is the code of the First VC and Third VC:
First VC .m:
#import "ViewController.h"
#import "ThirdViewController.h"
#interface ViewController ()<PassValueProtocal>
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#end
#implementation ViewController
{
ThirdViewController *thirdVC;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void) passValueBack:(NSString *)value
{
NSLog(#"HAHAH");
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)segueToSecondVC:(UIButton *)sender
{
thirdVC = [ThirdViewController sharedManager];
thirdVC.delegate = self;
}
#end
Third VC .h:
#import <UIKit/UIKit.h>
#protocol PassValueProtocal <NSObject>
- (void) passValueBack: (NSString *) value;
#end
#interface ThirdViewController : UIViewController
#property (weak, nonatomic) id<PassValueProtocal>delegate;
+ (id) sharedManager;
#end
Third VC .m:
#import "ThirdViewController.h"
#interface ThirdViewController ()
#property (weak, nonatomic) IBOutlet UITextField *myTextField;
#end
#implementation ThirdViewController
+ (id) sharedManager
{
NSLog(#"myDelegate sharedManager");
static ThirdViewController *sharedManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ sharedManager = [[self alloc] init]; });
return sharedManager;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)passValueAction:(UIButton *)sender
{
NSLog(#"%#", self.delegate);
if ([self.delegate respondsToSelector:#selector(passValueBack:)])
{
[self.delegate passValueBack:self.myTextField.text];
}
}
#end
Your code
- (IBAction)segueToSecondVC:(UIButton *)sender
{
thirdVC = [ThirdViewController sharedManager];
thirdVC.delegate = self;
}
Should not be here. You should implement function prepareForSegue and move this code there. Something like
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
ThirdViewController *thirdVC = (ThirdViewController *)segue.destinationViewController;
thirdVC.delegate = self;
}

Make some calculation on Viewcontroller, need show the result to another Viewcontroller

I have an app, where I making some calculation, and need to transfer result of this calculation to ViewController3 and show the result there. Now I use label in same ViewController2 where I have calculation. Thank you for your help.
ViewController2.h
#import <UIKit/UIKit.h>
#interface ViewController2 : UIViewController<UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UILabel *gasPrice;
#property (weak, nonatomic) IBOutlet UILabel *gasCarMileage;
#property (weak, nonatomic) IBOutlet UITextField *perGalon;
#property (weak, nonatomic) IBOutlet UITextField *miles;
#property(nonatomic, copy, readonly) NSString *result;
- (IBAction)getIt:(id)sender;
#end
ViewController2.m
#import "ViewController2.h"
#import "ViewController3.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
//Start calculation
- (IBAction)getIt:(id)sender; {
float perGalon = ([_perGalon.text floatValue]);
float miles = ([_miles.text floatValue]);
float mileCost = perGalon / miles;
[self performSegueWithIdentifier:#"viewController3" sender: nil];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"viewController3"]) {
ViewController3 *viewController3 = [segue destinationViewController];
viewController3.result = [[NSString alloc] initWithFormat: #"Every mile you drive
will cost you $ %f", mileCost];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.perGalon.delegate = self;
self.miles.delegate = self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
return [textField resignFirstResponder];
}
#end
ViewController3.h
#import <UIKit/UIKit.h>
#interface ViewController3 : UIViewController
#property(nonatomic, copy) NSString *result;
#end
ViewController3.m
#import "ViewController3.h"
#import "ViewController2.h"
#interface ViewController3 ()
#end
#interface ViewController2 ()
#property(nonatomic, copy, readwrite) NSString *result;
#end
#implementation ViewController3
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You can define a string property in View controller 3 which you will set when you push view controller 3 from view controller 2.
ViewController3 interface declaration
#interface ViewController2 ()
#property(nonatomic, copy) NSString *result;
#end
In ViewController 2, you will implement this line at the last of your getIt() method.
[self performSegueWithIdentifier:#"viewController3" sender: nil]
And implement another method called prepareForSegue as follows
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"viewController3"]) {
ViewController3 *viewController3 = [segue destinationViewController];
viewController3.result = "YOUR CALCULATION RESULT HERE"
}
}
Bear in mind, you have to set identifier for view controller 3, go to storyboard and select the view for view controller 3 and On identify inspector, specified Storyboard ID as "viewController3".
Use a protocol,
In ViewController2.h
#protocol ViewController2Delegate;
#property (strong, nonatomic) id<ViewController2Delegate> delegate;
#protocol BexAPIClientDelegate <NSObject>
- (void)ViewController2:(ViewController2 *)vc didCalculateCost:(CGFloat)cost;
#end
Then at the end of the getIt() call the delegate
[self.delegate viewController2:self didCalculateCost:gasCostPerMile];
You need to set ViewController3 to be ViewController2's delegate when you load it. Also you will need to setup ViewController3 to conform to the protocol.
Using the protocol is worth the effort as it will make your code clear and easy to manage.
Retain a string in VC3. While initializing the VC3 object, set the value from VC2. Update the label in VC3(in viewDidLoad method)

Pass Value in iOS

I created two pages, called ViewController and SecViewController. In ViewController, which is the first page, with one button and one label. And I set segue on a button to SecViewController, which is the second page.
I am trying to pass the segue identifier to page 2, but this is not success. I test the value passing in page1, the console display
2013-07-05 10:33:54.554 Testing2[1314:c07] 1, (null)
Here is my code:
Anyone can identify which code I typing wrong?
ViewController.h
#import <UIKit/UIKit.h>
#class SecViewController;
#interface ViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *label;
#property (strong, nonatomic) IBOutlet UIButton *button;
#property (strong, nonatomic) SecViewController *view2;
#end
ViewController.m
#import "ViewController.h"
#import "SecViewController.h"
#implementation ViewController
#synthesize label, button, view2;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"1"]){
view2.received = [segue identifier];
NSLog(#"%#, %#", [segue identifier], view2.received);
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[label setText:#"Game Start!"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
SecViewController.h
#import <UIKit/UIKit.h>
#interface SecViewController : UIViewController
#property (strong, nonatomic) id received;
#property (strong, nonatomic) IBOutlet UILabel *label;
#end
SecViewController.m
#import "SecViewController.h"
#implementation SecViewController
#synthesize label;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You don't have to create a property for the second view controller. You can get it in the prepareForSegue and access the received variable from the second view controller.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:#"1"]){
SecViewController *vc = [segue destinationViewController];
vc.received = [segue identifier];
NSLog(#"%#, %#", [segue identifier], vc.received);
}
}
if you nslog in the the secondviewcontroller for the value of the received what do you get?
#import "SecViewController.h"
#implementation SecViewController
#synthesize label;
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Received %#",self.received);
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

How to dismiss the keyboard when done editing a text field

I have a simple program where you can type text into a text field, hit an ok button, and a label updates with the text entered.
I want the iPhone keyboard to disappear when I hit the OK button, when I press a large button that is in the background covering the whole view, or when I hit the return button on the keyboard. I have been trying to use the
[textField resignFirstResponder]
method, but it is not working. The program compiles fine, but when this method is called from any one of those events, it stops, and I get a message saying:
Thread 1: signal SIGABRT"
What am I doing wrong?
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize txtName;
#synthesize lblMessage;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)doSomething:(UIButton *)sender
{
[txtName resignFirstResponder];
NSString *msg = [[NSString alloc] initWithFormat:#"Hello, %#", txtName.text];
[lblMessage setText:msg];
//[msg release];
}
- (IBAction)makeKeyboardGoAway:(UIButton *)sender
{
[txtName resignFirstResponder];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
#end
Here is the header file as well:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *txtName;
#property (weak, nonatomic) IBOutlet UILabel *lblMessage;
- (IBAction)doSomething:(UIButton *)sender;
- (IBAction)makeKeyboardGoAway:(UIButton *)sender;
#end
Well I got it working, but I still don't understand the error message I was getting.
Here is the code that worked for me.
Header:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
IBOutlet UITextField *txtName;
IBOutlet UILabel *lblMessage;
}
#property (nonatomic, retain) IBOutlet UITextField *txtName;
#property (nonatomic, retain) IBOutlet UILabel *lblMessage;
- (IBAction)doSomething;
- (IBAction)makeKeyboardGoAway;
#end
Implementation:
#import "ViewController.h"
#implementation ViewController
#synthesize txtName;
#synthesize lblMessage;
- (IBAction)doSomething
{
[txtName resignFirstResponder];
NSString *msg = [[NSString alloc] initWithFormat:#"Hello, %#",
txtName.text];
[lblMessage setText:msg];
//[msg release];
}
- (IBAction) makeKeyboardGoAway
{
[txtName resignFirstResponder];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Call this method when the OK button is clicked.
[self.view endEditing:YES];
This works....if everything lines up with this it might be something else in your code....
...also be sure to have all objects linked correctly (VC to TextField and Button....Button back to VC)...that could also cause the crash
.h
#interface ViewController : UIViewController {
IBOutlet UIButton *button;
IBOutlet UITextField *textfield;
IBOutlet UILabel *label;
NSString *string;
}
-(IBAction)dismiss:(id)sender;
#property (nonatomic, retain)UIButton *button;
#property (nonatomic, retain)UITextField *textfield;
#property (nonatomic, retain)UILabel *label;
.m
#synthesize textfield, button, label;
-(IBAction)dismiss:(id)sender {
[textfield resignFirstResponder];
string = [NSString stringWithFormat:#"Hello %#", textfield.text];
[label setText:string];
}

Resources