initialize instance variables on Objective-C - 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;
}
}

Related

clean up the instance of view after change

I found out, that every time I change the view the new instance of them will be created. (Memory increase every change of the view).
I would like to dealloc the actually view, if I go the the previous one.
This can not be done by dealloc, because I am using ARC.
The "BACK"-Button is just linked to the Config Menu. At the time I need to dealloc the error view to create the new instance next time.
The init of the Error view looks like:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
The other buttons of the config menu are also just linked to the next view. So I do not create the instance of them manually. If you need some other parts of code, I will put it in.
MORE CODE:
Config View:(almost empty, only 3 linked buttons)
#import "ConfigMenuViewController.h"
#interface ConfigMenu ()
#end
#implementation ConfigMenu
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end
ErrorView.m:
#import "Error.h"
#import "CANlinkWLAN.h"
#import "SocketConnectionControllerThread.h"
#interface Error ()
#end
#implementation Error
#synthesize canBufferOverflow;
#synthesize canTransmitTimeout;
#synthesize canErrorcounterOverflow;
#synthesize canBusOffError;
#synthesize usbtors232SyntexError;
#synthesize usbtors232FormatError;
#synthesize usbtors232BufferOverflow;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter ]addObserver:self selector:#selector(receivedMessage:) name:#"GET_ERROR_STATUS" object:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)readError:(id)sender {
[[SocketConnectionControllerThread sharedInstance] sendCommand: GET_ERROR_STATUS];
}
- (void) receivedMessage: (NSNotification *) note{
NSDictionary *userInfo = [note userInfo];
unsigned char error = [(NSNumber *)[userInfo objectForKey:#"GET_ERROR_STATUS"] integerValue];
NSLog(#"Error: %d", (int)error);
[self receivedError: &error];
}
- (void) receivedError:(unsigned char *) msg{
//change some colors ( not important) ;
}
- (void)dealloc{
[[NSNotificationCenter defaultCenter]removeObserver:self name:#"GET_ERROR_STATUS" object:nil];
}
#end
ErrorView.h
#import "ViewController.h"
#interface System : ViewController
{
UILabel *serverEcho;
UILabel *messageEcho;
UILabel *usbtors232Output;
}
- (IBAction)reset:(id)sender;
- (IBAction)setAutobaud:(id)sender;
- (IBAction)readFeedback:(id)sender;
- (void) receivedMessage: (NSNotification *) note;
#property (nonatomic, retain) IBOutlet UILabel *usbtors232Output;
#property (nonatomic, retain) IBOutlet UILabel *messageEcho;
#property (nonatomic, retain) IBOutlet UILabel *serverEcho;
#end
What happens with ARC is that there's a counter automatically incremented of all of the strong pointers to your object. If you set to nil all the strong pointers to it, ARC will automatically dealloc the memory allocated for the object. What you can do is implement the dealloc method in you ErrorView and log something. Then see if it's deallocated. Simply set to nil all pointers pointing to this object and the memory will be freed.
Edit more code :
I think your dealloc method is never called since you add yourself as an observer of UINotification and you remove yourself from it in the dealloc method (which is never called) so it creates a "memory loop" that you never get out of. Try calling
[[NSNotificationCenter defaultCenter]removeObserver:self name:#"GET_ERROR_STATUS" object:nil];
when you press the back button for example.
I found the way. It was much easier as I expected.
- (IBAction)goBack:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
That way I really go back to the previous view and release the allocated memory. +

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.

Doesn't Enter my constructor

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

Obj-C: Delegate method not getting called

I'm new to iOS Dev, I'm following the Stanford CS193P classes for Fall 2010. I'm on assignment 3 and I'm setting my delegate to my view and by using the debugger I'm noticing the call to my delegate method won't happen, I don't understand what could be happening. My code is as follows:
GraphViewController.h:
#interface GraphViewController : UIViewController <GraphViewDelegate> {
GraphView *graphView;
float scale;
}
#property (retain) IBOutlet GraphView *graphView;
#property float scale;
- (IBAction)zoomIn;
- (IBAction)zoomOut;
#end
GraphViewController.m:
#implementation GraphViewController
#synthesize graphView, scale;
- (NSString *)functionForGraph:(GraphView *)requestor {
NSLog(#"%#", #"culo peluo");
return #"lol";
}
- (float)scaleForGraph:(GraphView *)requestor {
return self.scale;
}
- (IBAction)zoomIn {
}
- (IBAction)zoomOut {
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.graphView.delegate = self;
self.scale = 20;
[self.graphView setNeedsDisplay];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
GraphView.h:
#class GraphView;
#protocol GraphViewDelegate
- (NSString *)functionForGraph:(GraphView *)requestor;
- (float)scaleForGraph:(GraphView *)requestor;
#end
#interface GraphView : UIView {
id <GraphViewDelegate> delegate;
}
#property (assign) id <GraphViewDelegate> delegate;
#end
GraphView.m:
#implementation GraphView
#synthesize delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect
{
CGFloat cgScale = [self.delegate scaleForGraph:self];
[AxesDrawer drawAxesInRect:self.bounds originAtPoint:self.center scale:cgScale];
}
- (void)dealloc
{
[super dealloc];
}
#end
Put a break point on the line where you set the graph view's delegate.
Inspect the graphView variable. Is it nil?
This happens to me all the time and it's always (well nearly always) because I have failed to connect the outlet to the view in interface builder.
Let's say class YourClass is a delegate for some other class. And delegate methods are not called, despite that delegate property is set up.
Most probably the problem is that your class instance, that is a delegate for your other class is released before the delegate method is called on it. Make it more persistent by making this class a property or instance variable of other class or by using dispatch_once. For example,
Change
YourClass *instance = [[YourClass alloc] init];
by
#property(nonatomic, strong) YourClass *instance;
self.instance = [[YourClass alloc] init];
This problem occurs because in ARC everything that is created inside a method (and is not an instance variable) is released, when method finishes. And delegate methods cannot be called, that are invoked by some background process.
I've written a big blog post on this problem. This is pretty common situation.
http://alwawee.com/wordpress/2013/07/31/on-xmppframework-delegate-method-not-being-called/
Ive got a few pointers for ya on this one:
You don't need an iVar (internal Variable) if you have the variable as a property, it will still work, I've never know it not to.
GraphView
#interface GraphView : UIView {
}
#property (assign) id <GraphViewDelegate> delegate;
#end
GraphViewController
#interface GraphViewController : UIViewController <GraphViewDelegate> {
}
#property (retain) IBOutlet GraphView *graphView;
#property float scale;
- (IBAction)zoomIn;
- (IBAction)zoomOut;
#end
You need to set your delegate in your view to be able to use it.
GraphViewController
#implementation GraphViewController
( ... )
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.delegate = self;
}
return self;
}
( ... )
#end
You are not calling the delegate functions anywhere in your GraphView.m. Try testing it out by placing this piece of code in your - (id)initWithFrame:(CGRect)frame method, right before you return.
[self.delegate functionForGraph:nil];
and see if it logs any message to the console.
Of course this is just to test the delegate implementation, you should actually be using this delegate call in some other method in your GraphView.m which is able to process your requestor

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!