How to pass value from subclass to super class during initialization - ios

Suppose, I've two view controller. ViewController1 is the sub class of ViewController2. From subclass (ViewController1), I called superclass init method & passed a value by parameter & assigned that value to the superclass variable. But In superclass (ViewController2)'s viewDidLoad method, that value is always null. Why ? How can I pass that value from sub to super so that I can get that value in super class's viewDidLoad method ?
ViewController1.h
#interface ViewController : ViewController2
#end
ViewController1.m
#implementation ViewController
- (instancetype)init
{
self = [super initWithName:#"Hello"];
if (self) {
NSLog(#"1 :");
}
return self;
}
- (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
ViewController2.h
#interface ViewController2 : UIViewController
#property (nonatomic, strong) NSString *name;
-(instancetype)initWithName:(NSString *)name;
#end
ViewController2.m
- (instancetype)initWithName:(NSString *)name
{
self = [super init];
if (self) {
self.name = name;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(#"2 : %#", self.name);
}
#end

I tired your code and it worked just fine. I suspect, that you don't instantiate your ViewController directly. Do you use storyboard in your project? If yes - you should override initWithCoder: in ViewController.
However, it is bad idea to set any properties of view controllers during init-family methods. According to Apple recommendations, all customisation should be done in -viewDidLoad or -viewWill/DidAppear methods.
If you absolutely in need to set name property from outside, it is better you assign it directly, not trough passing argument to init method.
One more thing - initWithNibName:bundle: is Designated initializer. It means, that your subclasses absolutely must in the end call it during initialisation chain.

Updated - 16-Mar-2016
Example :
ViewController1.h
#import <UIKit/UIKit.h>
#import "ViewController2.h"
#interface ViewController1 : ViewController2
#end
ViewController1.m
#import "ViewController1.h"
#interface ViewController1 ()
#end
#implementation ViewController1
-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
//self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil andUserName:#"Ramesh Annadurai"];
// we can use above init method or below method, both will work
self = [super initWithName:#"Test Name"];
if (self) {
[self.view setBackgroundColor:[UIColor brownColor]];
}
return self;
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
//self = [super initWithCoder:aDecoder];
// If you are using storyboard use this initWithCoder method.
self = [super initWithName:#"Test Name"];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end
ViewController2.h
#import <UIKit/UIKit.h>
#interface ViewController2 : UIViewController
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString *) userName;
- (instancetype)initWithName:(NSString *) userName;
#end
ViewController2.m
#import "ViewController2.h"
#interface ViewController2 ()
#property (strong, nonatomic) NSString *userName;
#end
#implementation ViewController2
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andUserName:(NSString *) userName
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.userName = userName;
}
return self;
}
- (instancetype)initWithName:(NSString *) userName
{
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.userName = userName;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"User Name : %#", self.userName);
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#end

Related

How to pass a variable between UIViewControllers

I have a Detail View Controller which contains data passed from a Table View:
#import "BRProjectsDetailViewController.h"
#interface BRProjectsDetailViewController ()
#end
#implementation BRProjectsDetailViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (IBAction)unwindBackToProjectsDetailViewController:(UIStoryboardSegue *)seque;
{
NSLog(#"unwindBackToHomeViewController!");
}
///used to feed data from homeview into detail view
-(void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(#"viewWillAppear");
NSString *name = self.projects[#"name"];
self.title = name;
NSString *description = self.projects[#"description"];
self.descriptionView.text = description;
}
I want to take the variable string labelled 'name' above and pass the contents of this to a collection view controller, currently coded below. At the moment, before doing conditioning I'm just trying to get a response from my NSLog. Currently it just returns null: . This is just an excerpt from the code: Can anyone help please?
#import "BRCollectionViewController.h"
#import "BRCollectionViewCell.h"
#import "BRProjectsDetailViewController.h"
#interface BRCollectionViewController ()
{
///add arrays for photos - to update once photos known
NSArray *imagesOne;
NSArray *imagesTwo;
}
#end
#implementation BRCollectionViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad {
//added this
NSString *name;
NSLog(#"%#", name);
//
}
#end

Passing NSString from one viewController to another without IBAction

I am trying to pass an NSString variable from one view controller to the other but I have only been able to find tutorials and information on doing this by the use of a button IBAction but and have not been able to pass it successfully. Are there any easy alternatives without using a button?
#import "DetailController.h"
#import "City.h"
#import "VideoController.h"
#interface DetailController ()
#end
#implementation DetailController
#synthesize city, ClubName, Price, Vip, Promo, remain,p,deal,money,camera,cam;
- (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.
UIFont *labelFont=[UIFont fontWithName:#"Deutsch Gothic" size:20.0];
UIFont *myFont=[UIFont fontWithName:#"Deutsch Gothic" size:30.0];
UIFont *titleFont=[UIFont fontWithName:#"Deutsch Gothic" size:40.0];
NSString * name= self.city.clubName;
NSString * line= self.city.clubLine;
NSString * description= self.city.promo;
NSString * price= self.city.price;
cam=self.city.camera;
remain.font=labelFont;
remain.text=#"VIP Remaining :";
p.font=labelFont;
p.text=#"Price :";
money.font=myFont;
deal.font=labelFont;
deal.text=#"Promotions :";
ClubName.font=titleFont;
ClubName.text=name;
Vip.font=myFont;
Vip.text=line;
Price.font=myFont;
Price.text=price;
Promo.font=labelFont;
Promo.text=description;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I am trying to pass cam or camera to videoController
If you are trying to Push between view controllers than you can create a property in view controller and before pushing view controller set the value.You can do this in following way:-
In View Controller2 declare a property
#property(nonatomic,strong) NSString *passedString;
in View Controller 1 do this
ViewController2 *vc2 = [ViewController2 alloc]initWithNibName:#"ViewController2" bundle:nil];
[vc setPassedString:#"Hello"];
[self.navigationController pushViewController:vc2 animated:YES];

trying to learn objective-c delegates. why wont my sample project work?

I am trying to pass data between two view controllers. viewcontroller2 is a delegate of viewcontroller.. note.. i called the delegate property "homie" yes I know this is bad practice but I am just messing around trying to understand the concept.
here is viewcontroller:
#import <UIKit/UIKit.h>
#protocol ViewControllerDelegate <NSObject>
#required
- (void)sendData:(NSString *)theString;
#end
#interface ViewController : UIViewController
#property (nonatomic, assign) id <ViewControllerDelegate> homie;
- (void)doSomething;
- (IBAction)doneText:(id)sender;
#end
implementation:
#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)doSomething{
}
- (IBAction)doneText:(id)sender {
UITextField *thisField = sender;
if([_homie respondsToSelector:#selector(sendData:)]){
[_homie sendData:[thisField text]];
}
}
now here is the other view controller implementing the first
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface ViewController2 : UIViewController <ViewControllerDelegate>
- (IBAction)hittingbtn:(id)sender;
#property (weak, nonatomic) IBOutlet UITextField *textfield;
#property (strong, nonatomic) ViewController *vc;
#end
implementation:
#import "ViewController2.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;
}
- (void)viewDidLoad
{
[super viewDidLoad];
ViewController *theview = [[ViewController alloc]init];
theview.homie = self;
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// DELEGATE METHOD
- (void)sendData:(NSString *)theString{
[_textfield setText:theString];
}
- (IBAction)hittingbtn:(id)sender {
}
#end
in viewdidload I instantiate the first viewcontroller, and set myself as its delegate. im assuming then when that viewcontroller2 runs the code in its method then it will see if its delegate has implemented the delegate method and use that code.. what am i missing here?
Your problem is that you use ViewControllers wrong. You have initialized ViewController
ViewController *theview = [[ViewController alloc]init];
theview.homie = self;
And what next? You haven't assign it to your properties or something. What have you do? It's simple. You have to implement - (void)prepareForSegue:sender:. First of all in your storyboard set segue's identifier. Then do following.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
ViewController *destinationViewController = (ViewController *)[segue destinationViewController];
ViewController.homie = self;
}
}
You need to set the delegate in prepareForSegue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController respondsToSelector:#selector(setHomie)]) {
[segue.destinationViewController setHomie:self];
//or
if ([[segue.destinationViewController isKindOfClass:[ViewController class]]) {
ViewController *destinationViewController = (ViewController *)[segue destinationViewController];
ViewController.homie = self;
}
//or the segue identifier which has already been mentioned
}

How do delegates work in objective c?

I'm trying to figure out delegates because I really need them for a project I'm working on, but for the life of me, I can't figure them out. No matter how much I tweak the code, nothing works
ViewController.h:
#import <UIKit/UIKit.h>
#class ViewController;
#protocol testDelegate
-(void)sayHi;
#end
#interface ViewController : UIViewController
- (IBAction)button:(id)sender;
#property (weak, nonatomic)id <testDelegate> delegate;
#end
ViewController.m:
#import "ViewController.h"
#import "DelegateController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
DelegateController *dc = [[DelegateController alloc] init];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)button:(id)sender {
[self.delegate sayHi];
}
#end
DelegateController.h:
#import "ViewController.h"
#interface DelegateController : UIViewController <testDelegate>
#end
DelegateController.m:
#import "DelegateController.h"
#interface DelegateController ()
#end
#implementation DelegateController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
NSLog(#"init");
ViewController *vc = [[ViewController alloc] init];
[vc setDelegate:self];
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
}
-(void)sayHi
{
NSLog(#"hi");
}
#end
The - (IBAction)button:(id)sender method is connect to a button, but when clicked I get no output. What am I doing wrong?
ViewController.h:
#import <UIKit/UIKit.h>
#protocol testDelegate
-(void)sayHi;
#end
#interface ViewController : UIViewController
#end
ViewController.m:
#import "ViewController.h"
#import "DelegateController.h"
#interface ViewController () <testDelegate>
#end
#implementation ViewController
- (IBAction)pushNewViewController:(id)sender
{
DelegateController *dc = [[DelegateController alloc] init];
dc.delegate = self;
[self.navigationController pushViewController:dc animated:YES];
}
- (void)sayHi
{
NSLog(#"It works!");
}
#end
DelegateController.h:
#import "ViewController.h"
#interface DelegateController : UIViewController
#property (weak, nonatomic) id<testDelegate> delegate;
#end
DelegateController.m:
#import "DelegateController.h"
#implementation DelegateController
- (IBAction)button:(id)sender
{
if([_delegate respondsToSelector:#selector(sayHi)]) {
[_delegate performSelector:#selector(sayHi)];
}
}
#end
Try this:
ViewController.h
#import <UIKit/UIKit.h>
#class ViewController;
#protocol testDelegate
-(void)sayHi;
#end
#interface ViewController : UIViewController
- (IBAction)button:(id)sender;
#property (weak, nonatomic)id <testDelegate> delegate;
#end
ViewController.m
#import "ViewController.h"
#import "DelegateController.h"
#interface ViewController ()
#property (nonatomic, strong) DelegateController *dc;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_dc = [[DelegateController alloc] init];
[self setDelegate:_dc];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)button:(id)sender
{
[self.delegate sayHi];
}
#end
DelegateController.h
#interface DelegateController : UIViewController <testDelegate>
#end
DelegateController.m
#import "DelegateController.h"
#interface DelegateController ()
#end
#implementation DelegateController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
NSLog(#"init");
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
}
-(void)sayHi
{
NSLog(#"hi");
}
#end
Your problem is that ViewController creates DelegateController, then in DelegateController you're creating a new, different, instance of ViewController, and setting yourself as the delegate of that instance. Normally, the way you set a delegate is that DelegateController would create an instance of ViewController and set itself as the delegate. This assumes that DelegateController is created first, but exactly how to do this depends on your app structure, and how you move from controller to controller.
Replace you button Click method with following
- (IBAction)button:(id)sender {
// Check whether your Delegate method is implemeted or not
if([delegate respondsToSelector:#selector(sayHi)])
{
// Call Delegate Method
[delegate performSelector:#selector(sayHi)];
}
}

cannot set the text of label in DetailViewController after passing data between different viewController

pass data from FirstViewController to DetailViewController. i can not set the text of label in DetailViewController; FirstViewController is a tableview and it is good.
i use method updateRowNumber to set the rowNumber . and in DetailViewController, i can use debugger to see the rowNumber is correct. but the label's text is not showed on the view.
anyone can help me out?
in my FirstViewController
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (dvController == nil)
{
DetailViewController *aController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
self.dvController = aController;
[aController release];
}
[[self navigationController] pushViewController:dvController animated:YES];
[dvController updateRowNumber:indexPath.row];
}
in my DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
{
int rowNumber;
IBOutlet UILabel *message;
}
#property(readwrite) int rowNumber;
#property(nonatomic, retain) IBOutlet UILabel *message;
- (void) updateRowNumber:(int) theindex;
#end
in my DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
#synthesize message, rowNumber;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void) updateRowNumber: (int) theindex
{
rowNumber = theindex + 1;
message.text = [NSString stringWithFormat:#"row %i was clicked", rowNumber];
}
- (void)dealloc
{
[message release];
[super dealloc];
}
- (void)viewDidLoad
{
message.text = [NSString stringWithFormat:#"row %i was clicked ", rowNumber];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Do any additional setup after loading the view from its nib.
}
- (void)viewWillAppear:(BOOL)animated
{
//message.text = [NSString stringWithFormat:#"row %i was clicked ", rowNumber];
[super viewWillAppear: animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear: animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You'll need to learn how the view is loaded, the process is well described in the documentation
What happens is that the view and all the outlets are nil until the view is loaded, you can make sure it is loaded by calling self.view; before configuring the outlet at updateRowNumber:
Please also note, you are better to call [super viewDidLoad] in the beginning of the overridden viewDidLoad, it makes sense as you need to let UIViewContorller to do it's staff before you do some customized logic, the dealloc is different as you need to do your logic before the standard NSObject -dealloc fires. Hope it's understandable.

Resources