Why does myArray not get initialized? - iphone

- (id)initWithStyle:(UITableViewStyle)style {
// Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
self = [super initWithStyle:style];
if (self) {
myArray = [[NSMutableArray alloc]init];
NSLog(#"ARRAY INITIALIZED"); //THIS NEVER OCCURS
}
return self;
}

Are you creating your table programmatically or is it in Interface Builder? If it's in interface builder, then you need to override -(id) initWithCoder:(NSCoder *)coder instead.

I would recommend just putting your initialization code in viewDidLoad or viewDidAppear. You would need to make sure you don't alloc multiple times (and orphan memory in the process), but it would get called regardless of whether this is rigged up in the xib or programmatically.
- (void)viewDidLoad
{
if(!myArray)
{
myArray = [[NSMutableArray alloc] init];
}
}

I can't really tell from your given code, but if you're making your controller programmatically, make sure you're initializing your subclass:
[[MyCustomTableViewController alloc] initWithStyle:style];
Rather than UITableViewController:
[[UITableViewController alloc] initWithStyle:style];

Found out that initWithStyle never gets called. I forgot to mention, the initial window is build in IB, so my custom controllers are called from the xib, and i have to override initWithCoder....
http://www.iosdeveloperforums.com/thread-initwithstyle-overriding

Related

Setting Property upon Initialization

I am creating an instance of a view controller and then presenting it modally on another view as such:
[viewController receiveNumber1:number1 andNumber2:number2];
[viewController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[self presentModalViewController:viewController animated:YES];
What I would like to do is set two properties within this new view controller upon initialization.
I can do this by calling a custom method like (somethings are int variables here):
[viewController methodProperty1:something1 andProperty2:something2];
However, I really need to set those properties right upon initialization because the content of the new view is dependent on those numbers.
Is there a way to pass on information to a new view while it is being initialized? Something like:
[[UIViewController alloc] initWithValue1:something1 andValue2:something2];
Also, I do not understand why
CustomViewController *view = [[CustomViewController alloc] init];
view.property = newValue; / [view setProperty:newValue];
does not work in this configuration, meaning the properties' values do not change. I can call methods within the new view and set its properties that way but not set the properties directly?
I'm sorry if these are lame questions, but I am sort of a beginner.
Thanks a bunch!
view.property = newValue and [view setProperty:newValue] are equivalent terminology.
You can implement one or multiple custom initialization methods for your view controller there is nothing that should stop from doing so. Have a look to the official doc to make sure you respect a couple of rules of how you should implement your custom initializer.
Your code snippet:
-(id)initWithValue1:(NSInteger)value1 andValue2:(NSInteger)value2
{
if (self = [super init])
{
_firstValue = value1;
_secondValue = value2;
return self;
}
else return nil; // or handle the error
}
In your CustomViewController.h, define two properties you want set and an initialization method, for example:
#property (nonatomic, assign) NSInteger firstValue;
#property (nonatomic, assign) NSInteger secondValue;
-(id)initWithFirstValue:(NSInteger)value1 andSecondValue:(NSInteger)value2;
Then, in your CustomViewController.m, implement the method you have declared earlier:
-(id)initWithFirstValue:(NSInteger)value1 andSecondValue:(NSInteger)value2
{
self = [super init];
if (self)
{
// Supposing you haven't synthesized your property and you are using
// latest Xcode build, instance variable are automatically created
_firstValue = value1;
_secondValue = value2;
}
return self;
}
Finally, you can allocate your controller using this line of code:
CustomViewController *controller = [[CustomViewController alloc] initWithFirstValue:value1ToSet andSecondValue:value2ToSet];
Some final advice
When you implement your custom initialization method, you should properly choose which init has to be called on super.
For instance, I prefer calling self = [super initWithFrame:CGRectZero]; if my controller is a subclass of UIViewController, or self = [super initWithStyle:UITableViewStylePlain]; if it is a subclass of UITableViewController.
There are other custom init method but you can find other information reading documentation about your custom controller superclass.

Reload data on UITableView

how to reload in UITableView class.
I am using the reloadData method but it's not working.
- (id)initWithCoder:(NSCoder *)coder
{
if (self = [super initWithCoder:coder])
{
[self init];
}
return self;
}
-(id)init
{
appdelegate=[[UIApplication sharedApplication]delegate];
[appdelegate readLiteratureFromDatabase];
tbl_obj.backgroundColor=[UIColor clearColor];
tbl_obj.delegate = self;
tbl_obj.dataSource = self;
[tbl_obj reloadData];
array_content = [[NSMutableArray alloc] init];
return self;
}
Here the init method call in another class. So at that time table are not reload.
please help!
From looking at your code it appears that you really need to read this;
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Introduction/introObjectiveC.html
You should not have a method called init that does not call up to super, that will eventually hose things.
Setting your docs ivar to an empty immutable string does nothing but waste memory. Eventually you will need to set docs to something real, wait till that point to do any allocation.
Next download the TableViewSuite sample from here;
http://developer.apple.com/library/ios/#samplecode/TableViewSuite/Introduction/Intro.html%23//apple_ref/doc/uid/DTS40007318
And take a look at the simple sample.
Please take the time to study that sample, it will help you understand table views.
May be that you might not have attached DataSource and Delegate to your XIB
or
You can do it through code using:
self.tableView.delegate = self;
self.tableView.datasource = self;
Also you have to add it as below:
#interface <YourViewControllerName>:UIViewController <UITableViewDelegate,UITableViewDataSource>
EDIT:
But you should try and understand that your controls like UITableView cannot be directly called and set into your UIView class.
It should be UIViewController only then it is possible to add and fillup the data into the TableView.
So your option is to call the data delegate and datasource methods and also the reloadData on the ViewController which works as parentView for the this UIView.
So unless you do this way, I fear that it is not possible.
Hope this helps you.
UIView does not have a reloadData method. UIView Class Reference
Maybe you can show your code so we can see what you are trying to do?
I had the same prob and i just used the viewDidLoad to add the data and in the end i used [super loadView]; and it reload.

ViewDidLoad being called before initWithNibName?

I'm having the strangest error, and i hope someone could help me.
Here is the code when I create a view controller and push it to navigationController.
the problem is passing the random variable to the new view controller. I tried passing it in the init method and also passing it with the line commented below.
MultipleBet *multipleBet = [[MultipleBet alloc] initWithMaxNumber:numbers andMaxStars:stars andRandom:self.random];
NSLog(#"RANDOM1: %d", self.random);
//[multipleBet setRandom:self.random];
UIBarButtonItem *backButton = [[[UIBarButtonItem alloc] init] autorelease];
backButton.title = #"Voltar";
self.navigationItem.backBarButtonItem = backButton;
[self.navigationController pushViewController:multipleBet animated:YES];
[multipleBet release];
However when i access the random variable in the viewDidLoad of the MultipleBet, it's always FALSE.
here is the code of the MultipleBet:
- (id)initWithMaxNumber:(int)maxNumbers andMaxStars:(int)maxStars andRandom:(BOOL)isRandom {
self = [super initWithNibName:#"MultipleBet" bundle:[NSBundle mainBundle]];
...
self.random = isRandom;
NSLog(#"RANDOM2: %d", self.random);
NSLog(#"RANDOM2.1: %d", isRandom);
return self;
}
and here is the code of the viewDidLoad:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"RANDOM2.2: %d", self.random);
}
i declare the variable and property like this:
BOOL random;
#property (nonatomic) BOOL random;
and the output is always:
RANDOM2.2: 0
RANDOM2: 1
RANDOM2.1: 1
RANDOM1: 1
Why is the NSLog from the viewDidLoad being outputted before all the others? it should be the last... Could it be because of my custom init method? I call the [super init], so it shouldn't be a problem...
viewDidLoad and init* methods are not guaranteed to execute one after the other. Code in your init* methods may cause the view to load, hence viewDidLoad will be called even if the init* method has not finished.
Most likely, some code in the part you omitted is causing the view to load. If you will show us that part, maybe we can point it out. Or, you can also move the self.random = isRandom; line as the first line inside your if (self) block and see if that works out. This way, whatever is causing the view to load will be executed after you have assigned self.random.
- (id)initWithMaxNumber:(int)maxNumbers andMaxStars:(int)maxStars andRandom:(BOOL)isRandom {
self = [super initWithNibName:#"MultipleBet" bundle:[NSBundle mainBundle]];
if (self) {
// do this first
self.random = isRandom;
NSLog(#"RANDOM2: %d", self.random);
NSLog(#"RANDOM2.1: %d", isRandom);
// do the other code after
...
}
return self;
}
I bumped into this problem. I was calling a method or property with self in the selector, e.g. self.bannerView.frame or [self createBannerView] from within the init* method.
Obviously, self is not completed initialization at that point, so apparently Apple has some code that will call viewDidLoad before accessing properties or methods.
My solution was to move the calls out of init and place them in viewDidLoad.
Probably in the part you left out (...) you are causing the view to load in some way. I.e., calling a setter in the initializer might cause you to do a [self.tableView reloadData] or something.

How can one create a generic (container)controller that will recieve as input another controller

In the app im creating there are many pages that look mostly the same with some part which is different. To handle this kind of situation i created a container controller that contains a subview. I want this subview to be filled by the contents of another controller (and its associated nib) which i will created dynamically as needed based on context.
I have the following method somewhere
- (void) someAction {
UIViewController* contentController = [[MyContentController alloc] init];
UIViewController* containerController = [[MyContainerController alloc] initWithContentController:contentController];
[navigationController pushViewController:pageController animated:YES];
[contentController release];
[containerController release];
}
In MyContainerController.m i retain the controller in a property
- (id)initWithContentController:(UIViewController *)aContentController {
if ((self = [super initWithNibName:#"MyContainerController" bundle:nil])) {
contentController = aContentController;
}
return self;
}
Later in viewDidLoad i do the following
- (void)viewDidLoad {
[super viewDidLoad];
[contentViewContainer addSubview:contentController.view];
}
contentViewContainer is the view that's supposed to hold the page specific info.
Unfortunatly this fails with EXC_BAD_ACCESS.
The funny thing is that if i alloc and init the content controller from within viewDidLoad everything works. It seems that i cant pass a contoller i allocated from another place.
Can anyone assist.
Since you are releasing contentController in the actionMethod
you have to retain contentController in you init method
- (id)initWithContentController:(UIViewController *)aContentController {
if ((self = [super initWithNibName:#"MyContainerController" bundle:nil])) {
contentController = [aContentController retain];
}
return self;
}
But, why do you need this? Controllers are supposed to control views and no other controllers. If you think you really need that then you want to use UINavigationController or UITabBarController maybe.
You can also load views without a controller (see here)
I personally think that having UIViewControllers inside of simple UIViewController is not a preferable approach
Hope it helps

UIVIewController custom init method

I want to implement a custom initialization method for my UIViewController subclass to "replace" the initWithNibName method.
This is the code:
- (id) initWithMessage:(NSString *)message {
if ((self = [super initWithNibName:#"ToolTip" bundle:nil])) {
label.text = message;
}
return self;
}
The label is loaded from xib but at this point the reference to the label is nil (probably because the xib is not loaded yet?). Does anyone know a solution for that? Thanks
I know this is an old question, but the correct answer is to use the viewDidLoad method to do any additional setup after the view has loaded. The view is not loaded until it's needed, and may be unloaded when a memory warning is received. For that reason, a view controller's view should not be touched in an init method.
You should declare the label programmatically and initialize it within the init rather than do it from the nib.
This is how :
Assume UILabel *label is a class variable with #property and #synthesize defined for it.
- (id) initWithMessage:(NSString *)message {
if ((self = [super initWithNibName:#"ToolTip" bundle:nil])) {
label = [[UILabel alloc] init];
label.text = message;
[self.view addSubView:label];
}
return self;
}
Release the label in the "dealloc" method.
Hope this helps.