Setting Property upon Initialization - iphone

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.

Related

why I can't transfer variables between two view controllers this way?

I have one view who calculates location and reverser geocode to get the zip code. Then it calls another view where I want to display weather results based on that zip code.
In the first view controller I do this once user clicks on the button to turn the page:
- (IBAction) showMyWeather : (id)sender {
WeatherApp *weather = [[WeatherApp alloc] initWithNibName:nil bundle:nil];
weather.zipcode = placemarkZip; //this one seems not to be doing the job
weather.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:weather animated:YES];
}
And at the WeatherApp I would like to read now zipcode, which is declared in this view controller .h:
#interface WeatherApp : UIViewController{
IBOutlet UIButton *done;
MKPlacemark *zipcode;
}
#property (nonatomic, retain) MKPlacemark *zipcode;
How can I use this code to transfer this zipcode to the WeatherApp? Thanks!
Yes, this is a fine way to pass information into your new object.
Alternatively, you could create a custom initializer for WeatherApp like
- (id)initWithZipCode:(NSString *)zip;
and then in the implementation file, it could be like this:
- (id)initWithZipCode:(NSString *)zip
{
self = [super init];
[self setZipcode:zip];
return self;
}
Finally, you could instantiate the class like so:
- (IBAction)showMyWeather:(id)sender
{
WeatherApp *weather = [[WeatherApp alloc] initWithZipCode:placemarkZip];
[weather setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentModalViewController:weather animated:YES];
[weather release]; // No longer needed with ARC... just sayin'
}
Finally, if you're going to continue to pass in information as you do above, I'd question why you're using initWithNibName:bundle:. If you're just going to pass nil to both, why not just use [[WeatherApp alloc] init]?

Why does myArray not get initialized?

- (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

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.

pass data to object of uiviewcontroller on iPhone

I have an iPhone app with a tableviewcontroller. When you click a certain cell it opens a new uiviewcontroller with this code:
nextViewController = [[avTouchViewController alloc] initWithNibName:#"avTouchViewController" bundle:nil];
The uiviewcontroller above called avTouchViewController has a property that looks like:
IBOutlet SomeObject *controller;
SomeObject is an object with all relevant view properties.
I would like to pass an nsstring parameter from the tableviewcontroller I initialize the avTouchViewController with to someObject.
How can I do this?
I'm a little confused by your question; you say you're creating your avTouchViewControllers when a cell is tapped inside an existing UITableView, but your last part describes the inverse situation.
Basically, if you want to pass information to a view controller, just give it a property that can be set (which may already be the case), e.g.:
nextViewController = [[avTouchViewController alloc] initWithNibName:#"avTouchViewController" bundle:nil];
nextViewController.controller = theInstanceOfSomeObjectIWantToPass;
You also may want to rename your controller property. To a reader, it doesn't make sense that a view controller has a property called controller which is actually a SomeObject*. As well, your class names should be capitalized, i.e. use AvTouchViewController instead of avTouchViewController.
If I were doing this I would add my own initializer to my UIViewController subclass:
- (id)initWithController:(NSString *pController) {
if (self = [super initWithNibName:#"avTouchViewController" bundle:nil]) {
self.controller = pController;
}
return self;
}
And then just call the following (in tableView:didSelectRowAtIndexPath: or whereever):
NSString *controller = #"Sample String";
AVTouchViewController *nextViewController = [[AVTouchViewController alloc] initWithController:controller];
[controller release];
[self.navigationController pushModalViewController:nextViewController animated:YES];
[nextViewController release];
As a point of style, class names conventionally begin with uppercase letters (hence my change to AVTouchViewController).