Doesn't Enter my constructor - objective-c

Im using the tabbed view application in xcode 4.3.
Im am simply trying to initislise some variables i have declared in my .h file of my FirstViewController. Im attempting this by creating a constructor in my .m file like so.
.h file:
#import <UIKit/UIKit.h>
#interface FirstViewController : UIViewController {
IBOutlet UITextField *currentGuess;
IBOutlet UILabel *attemptsMade;
IBOutlet UILabel *attemptsLeft;
IBOutlet UITextView *hints;
int numberToGuess;
int numberOfGuessesMade;
int maxGuesses;
int maxGenNumber;
NSMutableArray *allGuesses;
}
- (id) init;
#end
.m file
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
- (id) init {
NSLog(#"entered constructor!");
if(self = [super init])
{
numberToGuess = 0;
numberOfGuessesMade = 0;
maxGuesses = 3;
maxGenNumber = 10;
}
return self;
}

A UIViewController doesn't make sense to initialize with the init method.
Normaly you need - (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
If you building it from a XIB file, than do it like this
You need to place your initialization code in - (void)awakeFromNib or -(void)viewDidLoad.
Something like this for your case
#implementation FirstViewController
- (id) awakeFromNib {
NSLog(#"entered XIB constructor!");
numberToGuess = 0;
numberOfGuessesMade = 0;
maxGuesses = 3;
maxGenNumber = 10;
}
if non xib then:
- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle {
NSLog(#"entered constructor!");
if(self = [super initWithNibName:nibName bundle:nibBundle])
{
numberToGuess = 0;
numberOfGuessesMade = 0;
maxGuesses = 3;
maxGenNumber = 10;
}
return self;
}
And remember. init is not a "real" constructor as you would learn in OO class.

As noted in the UIViewController documentation, the designated initializer for UIViewController is initWithNibName:bundle:. But depending on how your view controller is created (e.g. in code or as part of a storyboard), this might not even be called, and it might be initWithCoder: instead.

If you are using nib. awakeFromNib method will be called. Also check whether use variants of init method like , initWithNibName, initWithframe etc.

Can you post the code where you create the VC? If you do it from an XIB init will not be called, instead of that you should re-write:
initWithNibName

Related

calling delegates in viewdidload

Quick question,
i have made a custom delegate
PupilView.h
#protocol DismissPupilViewPopoverDelegate
- (int) getPupilViewReason;
#end
#interface PupilView : UIViewController{
id<DismissPupilViewPopoverDelegate> delegate;
}
#property (nonatomic, assign) id<DismissPupilViewPopoverDelegate> delegate;
It is called in PupilView.m like follows
[[self delegate] getPupilViewReason];
in in my maincontroller.h
#import "PupilView.h"
#interface MainScreen : UIViewController<DismissPupilViewPopoverDelegate>
maincontroller.m
-(int) getPupilViewReason
{
return 100;
}
If i put the [[self delegate] getPupilViewReason]; in any function in pupilview.m it works perfectly, returns 100 i can see it with a breakpoint etc.
If i put it in viewdidload it dosn't load, returns 0, dosnt hit breakpoints etc. Any help as to why.
thanks
make a custom init method for the view controller where you pass the delegate so you can set the delegate in the init method before viewdidload is called.
#interface
- initWithDelegate:(id)aDelegate nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
//...
#end
#implementation
- initWithDelegate:aDelegate nibName:nibNameOrNil bundle:nibBundleOrNil{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_delegate = aDelegate;
///rest of init implementation
}
}
- (void)viewDidLoad{
[super viewDidLoad];
[self.delegate getPupilViewReason];
}
//...
#end
Go ahead and call. If the delegate is set up properly then it should work. Do you mean when you're doing a segue UI transfer?
Yes, you can call the delegate in viewDidLoad function.
Suppose your delegate(request owner) name is "delegate" then you can call like -
- (void)viewDidLoad
{
[super viewDidLoad];
[<OBJ>.delegate GetPupilViewReason];
}
OBJ - is the instance of a class, have assign the delegate.

UIView reference returns NULL pointed ARC enabled

I have ARC enabled so I am unsure as to why my reference is null.
My view controller instantiates a UIView ‘theGrid’ as soon as the view is loaded.
Later I have switch inside another class (MyOtherClass) that calls the UIViewContoller - (void) updateTheGrid:(id)sender method, that method is called as per the NSLog, but when I output the UIView to see if it is there, its returns null.
What am I doing wrong? It was my impression that ARC keeps up with everything. I feel like my trouble is coming from mm "MyOtherClass" when I ViewController * vc = [[ViewController alloc] init]; because I feel like that is just creating a new instance. But if that is the case, how am i suppose to reference the old instance and call the method?
NSLOG OUTPUT
[28853:c07] Intial Grid: <GridView: 0x8e423b0; frame = (0 0; 768 1024); layer = <CALayer: 0x8e43780>>
[28853:c07] Update The Grid (null)
GridView.h
#import <UIKit/UIKit.h>
#interface GridView : UIView
- (void) gridUpdated;
#end
GridView.m
#import "GridView.h"
#implementation GridView
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code
NSLog(#"initWithFrame");
}
return self;
}
- (void)drawRect:(CGRect)rect{
NSLog(#"Grid Draw Rect");
}
- (void) gridUpdated {
NSLog(#"GRID VIEW.m : Grid update called");
[self setNeedsDisplay];
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#import "GridView.h"
#interface ViewController : UIViewController {
GridView *theGrid;
}
#property (strong, retain) GridView * theGrid;
- (void) updateTheGrid : (id) sender;
#end
ViewController.m
#import "ViewController.h"
#import "GridView.h"
#interface ViewController () {}
#end
#implementation ViewController
#synthesize theGrid;
- (void)viewDidLoad {
[super viewDidLoad];
//draw the grid
theGrid = [[GridView alloc] initWithFrame:self.view.frame];
NSLog(#"Intial Grid: %#", theGrid);
[self.view addSubview:theGrid];
}
- (void) updateTheGrid : (id) sender{
NSLog(#"Update The Grid %#", theGrid);
[theGrid gridUpdated];
}
#end
MyOtherClass.m
- (void) mySwitch : (id) sender {
ViewController * vc = [[ViewController alloc] init];
[vc updateTheGrid:sender];
}
Do not allocate ViewController object again in your MyOtherClass.m because it will create an new instance of ViewController and your previous objects which holds ViewController wil get disposed including theGrid.
So please declare a weak property of ViewController inside the MyOtherClass.m and assign it while allocating MyOtherClass.m
Example:
ViewController class
moc = [[MyOtherClass alloc] initWithFrame:self.view.frame];
moc.vc = self;
MyOtherClass.h
#property(nonatomic,weak) ViewController *vc;
MyOtherClass.m
- (void) mySwitch : (id) sender {
[self.vc updateTheGrid:sender];
}
Note:Take care about the forward declarations :)

Passing data to textView from another class

I know this is just a fundamental question but still somewhere I am missing something, I am playing with passing data to a textView from another class. For this I have created two classes one with xib file (ViewController) and another without(secondVC).
What I am trying to do is that I have a textview in ViewController class and wanted to pass the data to this textView from secondVC. This is how I am doing.
//ViewController.h
#import <UIKit/UIKit.h>
#import "secondVC.h"
#interface ViewController : UIViewController{
IBOutlet UITextView *textView;
}
#property (nonatomic, retain) UITextView *textView;
- (IBAction)go:(id)sender;
#end
//ViewController.m
- (IBAction)go:(id)sender{
secondVC *sec = [[secondVC alloc] init];
[sec print];
}
//secondVC.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface secondVC : UIViewController
- (void)print;
#end
//secondVC.m
- (void)print{
NSString *printThis = #"This works";
ViewController *vc = [[ViewController alloc] init];
[vc.textView setText:printThis];
//vc.textView.text = printThis //Tried both
}
Any suggestions would be appreciated.
Thanks
you can do like this :
//ViewController.h
#import <UIKit/UIKit.h>
#import "secondVC.h"
#interface ViewController : UIViewController{
IBOutlet UITextView *textView;
}
#property (nonatomic, retain) UITextView *textView;
- (IBAction)go:(id)sender;
#end
//ViewController.m
- (IBAction)go:(id)sender{
secondVC *sec = [[secondVC alloc] init];
sec.viewController = self;
[sec print];
}
//secondVC.h
#import <UIKit/UIKit.h>
#import "ViewController.h"
#interface secondVC : UIViewController {
ViewController *viewController;
}
#property(nonatomic, retain)ViewController *viewController;
- (void)print;
#end
//secondVC.m
#synthesize viewController;
- (void)print{
NSString *printThis = #"This works";
self.viewController.textView.text = printThis ;
}
Try with protocol... if you want to send string from textView(child) to other ViewController(parent)
You need a delegate method that is fired from the SecondVC and handled in the first one (ViewController).
There are a few issues here:
You've got a ViewController creating a new secondVC and sending it a print message. That's okay, but the implementation of -print creates a different instance of ViewController and tries to set the text of it's textView property. That's clearly not what you want -- you should instead be sending the text back to the original instance of ViewController.
That second instance of ViewController very likely has its textView property set to nil since textView is an outlet, but you haven't loaded its view from the .xib.
It's really not nice for one view controller to mess with the views of another view controller. The secondVC should be giving the text to the original ViewController object, not trying to set the text of one of its views.
To facilitate communication from secondVC to ViewController, give secondVC a property to keep track of the original ViewController. The usual thing to do here is to define a delegate protocol for secondVC and implement that protocol in ViewController. When ViewController creates secondVC, it sets the delegate of secondVC to itself. That gives secondVC a pointer to its delegate (it shouldn't care whether its a ViewController or some other kind of object, as long as the delegate implements the right methods).
.h file:
#import <UIKit/UIKit.h>
#protocol StringDelegate <NSObject>
-(void)getArrayOfStrings:(NSMutableArray*)strArray;
#end
#interface WWSettings : UIViewController{
}
#property(nonatomic,assign)id<StringDelegate>delegate;
#end
.m file:
#import "WWSettings.h"
#implementation WWSettings
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)blablablaFunction{
[delegate getArrayOfStrings:yourArray];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
#end
if you dont understand how it works .. ask ! i'll make my best to help you )
your secondVC
#import <UIKit/UIKit.h>
#import "WWSettings.h"
#interface secondVC : UIViewController<StringDelegate>{
WWSettings *obj;
}
#end
and .m file :
#import "secondVC.h"
#implementation secondVC
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)getArrayOfStrings:(NSMutableArray *)strArray{
// here you get your array !!! it's a delegate function made by you in child viewController;
}
- (void)viewDidLoad
{
obj = [[WWSettings alloc]init];
[obj setDelegate:self];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
first VC .h file :
#import <UIKit/UIKit.h>
#protocol textViewChildDelegate <NSObject>
-(void)getStrings:(NSString*)string;
#end
#interface textViewChild : UIViewController<UITextViewDelegate>{
UITextView *textView;
}
#property(nonatomic,assign)id<textViewChildDelegate>delegate;
#end
.m file:
#import "textViewChild.h"
#implementation textViewChild
#synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)myWorkingMethod{
// get string from textView
[delegate getStrings:textView.text];
}
- (void)viewDidLoad
{
textView = [[UITextView alloc]initWithFrame:CGRectMake(0, 240, 320, 240)];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
Now go to secondVC .h:
#import <UIKit/UIKit.h>
#import "textViewChild.h"
#interface TextViewViewController : UIViewController<textViewChildDelegate>{
UITextView * myfirstTextView;
}
#end
and to .m file:
#import "TextViewViewController.h"
#implementation TextViewViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)getStrings:(NSString *)string{
myfirstTextView.text = string; // finally we get string from child view controller
}
- (void)viewDidUnload
{
myfirstTextView = [[UITextView alloc]init];
[super viewDidUnload];
// Release any retained subviews of the main view.
}

initialize instance variables on Objective-C

I'm developing an iPhone 3.1.3 application and
I have the following header file:
#import <UIKit/UIKit.h>
#interface VoiceTest01ViewController : UIViewController {
IBOutlet UITextView *volumeTextView;
BOOL isListening;
NSTimer *soundTimer;
}
#property (nonatomic, retain) IBOutlet UITextView *volumeTextView;
#property (nonatomic, retain) NSTimer *soundTimer;
- (IBAction)btnStartClicked:(id)sender;
#end
And .m file is:
#import "VoiceTest01ViewController.h"
#implementation VoiceTest01ViewController
#synthesize volumeTextView;
#synthesize soundTimer;
...
How can I set isListening up to false at start?
All instance variables are set to 0/NULL/nil by default, which in the case of a BOOL means NO. So it already is NO (or false) by default.
If you need any other value then you need to override the designated initializer(s), most of the time init, and set the default value there.
Set the boolean value in your viewDidLoad
- (void)viewDidLoad {
isListening = NO;
//Something
}
The default value for a BOOL field is False, but it's a good place set it in the "viewDidLoad" just as #BuildSucceeded sugest
Greetings
1) init is a good place, like below, but if you are using story board this init method won't be called.
- (id) init {
self = [super init];
if (self) {
isListening = NO;
}
return self;
}
2)
initWithCoder is a good place for your code if you are using storyboard of course your sdk is 3.0, i believe it has not storyboard at that time, but just in case anyone need it:
- (id) initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
isListening = NO;
}
return self;
}
3) If your viewcontroller will be init from nib file:
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
isListening = NO;
}
}

How to Initialize custom class/object within controller using Objective-C on the Iphone

I've got a simple "model" class like so (complete with constructor of course)
#implementation Widget
#synthesize name;
#synthesize color;
- (id) init
{
if (self = [super init])
{
self.name = #"Default Name";
self.color = #"brown";
}
return self;
}
#end
I've declared it as an internal member to my controller like so:
#import <UIKit/UIKit.h>
#import "Widget.h"
#interface testerViewController : UIViewController {
IBOutlet UITextField *stuffField;
Widget *widget;
}
#property (nonatomic, retain) UITextField *stuffField;
#property (nonatomic, retain) Widget *widget;
- (IBAction)buttonPressed:(id)sender;
#end
and... I'm trying to initialize it within my controller like so:
#import "testerViewController.h"
#implementation testerViewController
#synthesize stuffField;
#synthesize widget;
- (IBAction)buttonPressed:(id)sender
{
stuffField.text = widget.name;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
widget = [[Widget alloc] init];
}
return self;
}
but.. it doesn't seem to be initializing my object because my textfield comes up blank every time. Any clues?
Try to use
-(void) viewDidLoad{} method to initiliaze your data
in your interface class use #class Widget instead of #import "Widget.h"
and in your implementation class use #import "Widget.h"
and make sure you come into your buttonPressed handler!