iOS presentViewController Delegates Returning Black Screen - ios

I have created two views within my project. I want to be able to click a button on my main view and the other view (ChooseCar) will pop up allowing the user to pick something then it will reopen the old view (ViewController) with the information entered. I have done the code for it but for some reason when I click the button the screen just goes black with nothing happening, i'm pretty sure it's something very simple I just can't get my head around it.
I will attach the code for the views below, thanks.
ViewController.h
//
// ViewController.h
//
// Created by Curtis Boylan on 24/11/2016.
// Copyright © 2016. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "ChooseCar.h"
#interface ViewController : UIViewController <ChooseCarDelegate>
- (IBAction)chooselocation;
#property (strong, nonatomic) IBOutlet UILabel *wherelocation;
#end
ViewController.m
//
// ViewController.m
//
// Created by Curtis Boylan on 24/11/2016.
// Copyright © 2016. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
- (IBAction)chooselocation {
ChooseCar *acController = [[ChooseCar alloc] init];
// acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];}
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(#"This was returned from ChooseCar %#",item);
}
#end
ChooseCar.h
//
// ChooseCar.h
//
// Created by Curtis Boylan on 24/11/2016.
// Copyright © 2016. All rights reserved.
//
#import <UIKit/UIKit.h>
#class ChooseCar;
#protocol ChooseCarDelegate <NSObject>
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item;
#end
#interface ChooseCar : UIViewController
#end
ChooseCar.m
//
// ChooseCar.m
//
// Created by Curtis Boylan on 24/11/2016.
// Copyright © 2016. All rights reserved.
//
#import "ChooseCar.h"
#interface ChooseCar ()
#property (nonatomic, weak) id <ChooseCarDelegate> delegate;
#end
#implementation ChooseCar
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSString *itemToPassBack = #"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#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 {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end

Its easy to do:
1)I believe your ChooseCar vc is created in storyboard.
if yes, you should set the Storyboard ID like this:
2)In your ViewController.m, update your chooselocation method to this:
- (IBAction)chooselocation {
//ChooseCar *acController = [[ChooseCar alloc] init];
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ChooseCar *acController = [sb instantiateViewControllerWithIdentifier:#"ChooseCar"];
[self presentViewController:acController animated:YES completion:nil];
}
EDIT
If you want to pass a value by delegate:
at the base of my give.
1)cut this code #property (nonatomic, weak) id <ChooseCarDelegate> delegate; from your ChooseCar.m to ChooseCar.h , make sure the ChooseCar.h like this:
#import <UIKit/UIKit.h>
#class ChooseCar;
#protocol ChooseCarDelegate <NSObject>
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item;
#end
#interface ChooseCar : UIViewController
#property (nonatomic, weak) id <ChooseCarDelegate> delegate;
#end
2) In the ViewController.m, you should abide the protocal, and set caController's delegate.
#import "ChooseCar.h"
#import "ViewController.h"
#interface ViewController () <ChooseCarDelegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
- (IBAction)chooselocation {
//ChooseCar *acController = [[ChooseCar alloc] init];
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ChooseCar *acController = [sb instantiateViewControllerWithIdentifier:#"ChooseCar"];
acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];
}
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(#"This was returned from ChooseCar %#",item);
}
#end
3)If you want to pass the value, you should take this code to your action:
NSString *itemToPassBack = #"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];

Replace your code with the following:
ViewController.h
#import <UIKit/UIKit.h>
#import "ChooseCar.h"
#interface ViewController : UIViewController <ChooseCarDelegate>
- (IBAction)chooselocation;
#property (strong, nonatomic) IBOutlet UILabel *wherelocation;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
{
ChooseCar *acController;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
- (IBAction)chooselocation {
acController = [self.storyboard instantiateViewControllerWithIdentifier:#"ChooseCar"];
acController.delegate = self;
[self presentViewController:acController animated:YES completion:nil];
}
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item
{
[acController dismissViewControllerAnimated:true completion:nil];
NSLog(#"This was returned from ChooseCar %#",item);
}
#end
Also set the storyboard id in storyboard. For more details see the attached screenshot:
ChooseCar.h
#import <UIKit/UIKit.h>
#class ChooseCar;
#protocol ChooseCarDelegate <NSObject>
- (void)addItemViewController:(ChooseCar *)controller didFinishEnteringItem:(NSString *)item;
#end
#interface ChooseCar : UIViewController
#property (nonatomic, weak) id <ChooseCarDelegate> delegate;
#end
ChooseCar.m
#import "ChooseCar.h"
#interface ChooseCar ()
#end
#implementation ChooseCar
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// NSString *itemToPassBack = #"Pass this value back to ViewControllerA";
// [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)backButtonClicked:(id)sender {
NSString *itemToPassBack = #"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];
}
/*
#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 {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end

Related

How to call delegate when VC is dismissed?

I have two VC. I need to call the delegate function when the 2nd VC is dismissed.
In my 1st VC or main VC I have given the following code in .h file.
#interface FirstVC : ....<SecondVCDelegate>
-(void)didDismissViewController:(UIViewController*)vc;
But for some reason SecondVCDelegate in this is not detected.
while presenting 2nd VC from first I have given this .m file of 1st VC.
SecondVC *optionsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondVC"];
optionsVC.delegate = self;
optionsVC.view.backgroundColor = [UIColor blackColor];
optionsVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:optionsVC animated:YES completion:^{}];
in 2nd VC .h file
#protocol SecondVCDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
#end
#interface SecondVC : ...
#property (nonatomic) id<SecondVCDelegate> delegate;
#end
in 2nd VC .m file I have dismissed using the below code
[self dismissViewControllerAnimated:YES completion:nil];
Could you point out what I did wrong with possible explanation. Thanks in advance.
This is the working code on xcode 9 :
ViewController.m :
#import "ViewController.h"
#import "SecondViewController.h"
#interface ViewController () <SecondVCDelegate>
#end
#implementation ViewController
- (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)action:(id)sender {
SecondViewController *optionsVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
optionsVC.delegate = self;
optionsVC.view.backgroundColor = [UIColor blackColor];
optionsVC.modalPresentationStyle = UIModalPresentationOverFullScreen;
[self presentViewController:optionsVC animated:YES completion:nil];
}
-(void) didDismissViewController:(UIViewController *)vc{
NSLog(#"working controller : %#", vc);
}
#end
SecondViewController.h :
#import <UIKit/UIKit.h>
#protocol SecondVCDelegate <NSObject>
- (void)didDismissViewController:(UIViewController*)vc;
#end
#interface SecondViewController : UIViewController
#property (weak, nonatomic) id<SecondVCDelegate> delegate;
#end
SecondViewController.m :
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (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)didmissAction:(id)sender {
[self dismissViewControllerAnimated:true completion:^{
[_delegate didDismissViewController:self];
}];
}
#end
On your 2nd VC .m do like this
First synthesize delegate below implementation
#synthesize delegate;
after that use it on viewController dismiss:
[self dismissViewControllerAnimated:YES completion:^{
[self.delegate didDismissViewController: self];
}];

Why is my delegate method not called in a storyboard?

I have two UIViewControllers embedded in a UINavigationController. The first view controller has the following source code :
ViewController.h :
#import <UIKit/UIKit.h>
#import "ViewController_2.h"
#interface ViewController : UIViewController <HanselDelegate>
#property (strong, nonatomic) IBOutlet UILabel *TestLabel;
- (IBAction)ButtonClick:(id)sender;
#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.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)ButtonClick:(id)sender {
NSLog(#"To call the second UIViewController...");
[self performSegueWithIdentifier:#"idCallSecond" sender:self];
}
-(void)SetFirstLabel {
NSLog(#"To run the delegate method...");
_TestLabel.text = #"Hello from the second...";
}
#end
The second controller has the following code:
ViewController2.h :
#import <UIKit/UIKit.h>
#protocol HanselDelegate <NSObject>
-(void)SetFirstLabel;
#end
#interface ViewController_2 : UIViewController
#property (nonatomic, weak)id<HanselDelegate> delegate;
- (IBAction)Button2Click:(id)sender;
#end
ViewController2.m:
#import "ViewController_2.h"
#interface ViewController_2 ()
#end
#implementation ViewController_2
- (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)Button2Click:(id)sender {
if ([self.delegate respondsToSelector:#selector(SetFirstLabel)]) {
NSLog(#"To call the delegate method");
[self.delegate SetFirstLabel];
}
[self.navigationController popViewControllerAnimated:YES];
}
#end
If I press the button in ViewController2, the method SetFirstLabel doesn't get called. Why is it so? Did I forgot something?
You forgot to set the delegate in ViewController.m
set this in ViewController.m
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"idCallSecond"]) {
ViewController_2 * vc2 = [segue destinationViewController];
vc2.delegate = self;
}
}

UIBarButtonItem Cancel does not work

I want to cancel the second view controller with a UIBarButtonItem, but I just don't get the code right. Please help.
Viewcontroller.h
#import <UIKit/UIKit.h>
#import "SecondViewController.h"
#interface ViewController : UIViewController <SecondViewControllerDelegate>
#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.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController isKindOfClass:[SecondViewController class]]) {
SecondViewController *vc2 = segue.destinationViewController;
vc2.delegate = self;
}
}
-(void)dismissViewController
{
NSLog(#"dismissed");
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
Secondviewcontroller.h
#import <UIKit/UIKit.h>
#protocol SecondViewControllerDelegate <NSObject>
- (void) dismissViewController;
#end
#interface SecondViewController : UIViewController
#property (weak, nonatomic) id <SecondViewControllerDelegate> delegate;
- (IBAction)backBarButtonItemPressed:(UIBarButtonItem *)sender;
#end
BackbarButton means cancelbutton
Secondviewcontroller.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
- (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)backBarButtonItemPressed:(UIBarButtonItem *)sender {
[self.delegate dismissViewController];
}
#end
You can dismiss in secondViewController,I do not see the meaning of Delegate in your code
- (IBAction)backBarButtonItemPressed:(UIBarButtonItem *)sender {
[self dismissViewControllerAnimated:true completion:nil];
}
If you use show segue,and you have a navigationController with these two ViewControllers,Use
- (IBAction)dismiss:(id)sender {
[self.navigationController popViewControllerAnimated:true];
}

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;
}

respondsToSelector Cannot be Called?

Sorry about the confusion.
What I want to do:
enter a string in a textfield in a view(EnterCommandViewController) and click save button, which will dismiss current view and go back to another view(DetectionViewController) and show the string in the UILabel in current view(DetectionViewController). So I have put define the delegate protocol in EnterCommandViewController, my question is that why the respondToSelector, which is used to check whether someone is listening does not work.
I am really a beginner in iOS, I am right now writing a delegate to send text got form UITextField to a UILabel, But I found that the respondToSelector cannot be called by using NSLog for testing.
Below is my code for reference:
EnterCommandViewController.h
#import <UIKit/UIKit.h>
#import "RscMgr.h"
#protocol EnterCommandDelegate <NSObject>
-(void) commandEntered:(NSString*)command;
#end
#interface EnterCommandViewController : UIViewController <RscMgrDelegate>
{
RscMgr* rscMgr;
__weak IBOutlet UITextField *inputTextField;
__unsafe_unretained id<EnterCommandDelegate> delegate;
}
-(void)sendMessage:(NSString*)message;
- (IBAction)cancelPressed;
- (IBAction)savePressed;
#property (nonatomic,assign)id delegate;
#end
EnterCommandViewController.m
#import "EnterCommandViewController.h"
#interface EnterCommandViewController () <UITextFieldDelegate>
{
#private
BOOL connected;
}
#end
#implementation EnterCommandViewController
#synthesize delegate;
- (void)viewDidLoad {
[super viewDidLoad];
rscMgr = [[RscMgr alloc] init];
[rscMgr setDelegate:self];
// Do any additional setup after loading the view, typically from a nib.
inputTextField.text=#"";
[inputTextField becomeFirstResponder];
}
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
inputTextField.delegate = self;
}
-(void) viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
inputTextField.delegate = nil;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)cancelPressed {
[self dismissViewControllerAnimated:YES completion:^{}];
}
- (IBAction)savePressed {
//is anyone listening
NSLog(#"the command is %#",inputTextField.text);
NSLog(#"Checking -- SomeMethod is listening");
if([delegate respondsToSelector:#selector(commandEntered:)]){
NSLog(#"SomeMethod is listening");
//send delegate function with the command entered by the user
[delegate commandEntered:inputTextField.text];
}
[self dismissViewControllerAnimated:YES completion:^{}];
}
DetectionViewController.h
#import <UIKit/UIKit.h>
#import "EnterCommandViewController.h"
#interface DetectionViewController : UIViewController <EnterCommandDelegate>{
__weak IBOutlet UILabel *showCommand;
}
- (IBAction)showSettings:(UIBarButtonItem *)sender;
#end
DetectionViewController.m
#import <Foundation/Foundation.h>
#import "DetectionViewController.h"
#implementation DetectionViewController
- (IBAction)showSettings:(UIBarButtonItem *)sender {
}
-(void) viewDidLoad{
[super viewDidLoad];
showCommand.text=#"";
EnterCommandViewController* enterCVC = [[EnterCommandViewController alloc] init];
enterCVC.delegate = self;
}
#pragma mark - EnterCommandDelegate function(s)
-(void) commandEntered:(NSString *)command{
// showCommand.text = command;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"command: %#",command);
[self->showCommand setText:command];
});
}
#end
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
You are not setting the delegate properly.
EnterCommandViewController* enterCVC = [[EnterCommandViewController alloc] init];
enterCVC.delegate = self;
This is not the way of setting the delegate in your case, since you are not using the created instance of enterCVC, instead a new instance is created from the storyboard when you are transitioning toEnterCommandViewController `(From your comment its clear that you are using the storyboard for this).
So what you can do is you should the delegate from prepareForSegue in DetectionViewController like
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get reference to the destination view controller
EnterCommandViewController* enterCVC = [segue destinationViewController];
enterCVC.delegate = self;
}

Resources