sending variables to the added subview view controller - iphone

I know how to retrieve variables from your parent view...
which is by doing something like this
[(mainViewController *)[self.superview] variableName];
but now i would like to know how to send variable data to a subview...
specially if i do something like this
ScreenTwoViewController *screen2 = [[ScreenTwoViewController alloc] init];
...
...
[self.addSubview:screen2.view];
in screenTwo i have a variable name Message:
I would like to send a variable message to the actual view so it can display the message in that view based on what the parent view sends it when adding the screen2 view as a subview??

Well if you have set the property for the variables in the subview like this.
#property (nonatomic, retain) NSString *message;
and also synthesis it in your .m file than you can always use this
screen2.message = [[NSString alloc] initWithFormat:#"use what ever init methode that you want"];
and dont forget to release the screen2 before the end of the method to avoid memory leaks

Do you have a setter for Message? If not, is it a property? Either way, I would have a getter method, setMessage:(NSString *)msg with the following implementation:
- (void)setMessage:(NSString *)msg {
[message release];
message = [msg retain];
// put your code to modify your UI here
}
This way, you're tying the assignment of the variable with the update of the view.

You could create a new init method for ScreenTwoViewController. For example, - (id) initWithMessage:(NSString *)message.
To update the message just create a setter method - (void)setMessage:(NSString *)newMessage.

Related

How do I create property for subclass of Apple's class

I am trying to access an instance of SVSegmentedControl
It's a subclass of UIControl.
I created that instance during viewDidLoad
SVSegmentedControl *mySC = [[SVSegmentedControl alloc] initWithSectionTitles:[NSArray arrayWithObjects:#"Normal", #"Limosine", #"Any", nil]];
It does have a method - (void)segmentedControlChangedValue:(SVSegmentedControl*)segmentedControl { which I will be able to access the instance when the value is changed. But how do I access the instance(mySC) at other parts of the code?
Set a property in your UIViewController, and instead of creating a new instance variable, set the property to the newly initialised segmented controller. And from there on you can access it outside the viewDidLoad's scope.
Edit...
You really need to learn how to propertize / setter & getter a variable rather than asking people to post code for you.
Below the } in the header file:
#property (nonatomic, retain) SVSegmentedControl *control;
Top of the implementation file
#synthesize control;
To set it:
self.control = [[[SVSegmentedControl alloc] init...] autorelease];
It should be set to nil in the dealloc method.

message sent to deallocated instance ! cant find error

alright I am looking for this error since 2 hours and I just cant figure it out please help me.
I have the following situation I have 2 viewcontroller.
one presents the other one as modalview like that.
SearchViewController *searchViewController = [[SearchViewController alloc]init];
[searchViewController setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
searchViewController.delegate = self;
searchViewController.senderTag = [sender tag];
[self presentModalViewController:searchViewController animated:YES];
[searchViewController release];
in my searchviewcontroller I do this in the .h file
BSKmlResult *selectedAirport;
#property (nonatomic, retain) BSKmlResult *selectedAirport;
in the .m file i synthesize it and then set it like that
selectedAirport = [self.airportList objectAtIndex:indexPath.row];
and then release it here
- (void)dealloc {
[selectedAirport release];
[super dealloc];
}
in the delegate methode of my SearchViewController which is implemented in the first
viewcontroller where I also present the SearchViewController
i have the following
if (controller.selectedAirport) {
if (departureAirport) {
[departureAirport release];
}
departureAirport = [controller.selectedAirport copy];
}
[self dismissModalViewControllerAnimated:YES];
I narrowed down where the error happens it is in the dealloc of my SearchViewController
[selectedAirport release];
but I cant figure out where my mistake is
please help
selectedAirport = [self.airportList objectAtIndex:indexPath.row];
You arent retaining selectedAirport here.
Change it to
self.selectedAirport = [self.airportList objectAtIndex:indexPath.row];
Since you couldnt find it out, probably you dont know this...
If you dont access member variables by self.memberVariable, you are not accessing its property. Thus, it was not getting retained.
Ofcourse you can also retain it by saying
selectedAirport = [[self.airportList objectAtIndex:indexPath.row] retain];
But whats the use of your property then...
You need to use self. to run it through the synthesized method, to get the retain.
self.selectedAirport = [self.airportList objectAtIndex:indexPath.row];
I know this post is quite old but just wanted to add something useful to it. In the above case the member variable name and property name are identical so you may still by mistake set the value of member variable instead accessing it using property that will call retain implicitly. Hence the best way to make sure you always use self.selectedAirport is to name the member variable something different than your property.
For example, in .h file you can have below implementation:
NSString *_selectedAirport;
then encapsulate it inside a property like below
#property(nonatomic,retain) NSString *selectedAirport;
and in .m implementation file synthesize it like below:
#synthesize selectedAirport = _selectedAirport;
By doing above, if you try to access it like below
selectedAirport = [self.airportList objectAtIndex:indexPath.row];
then it would result in an error and you will be prompted to use self.selectedAirport.
Also in this case your dealloc method can have either
self.selectedAirport = nil;
or
[_selectedAirport release];

Data is not persisting in multiple instances of the same object (iOS)

I'm having issues with data persisting inside of multiple instances of objects I'm creating.
I have a class "IconViewController" that extends UIViewController that I pass information to, such as the name of the image it should be using:
//IconViewController.h
#interface AppIconViewController : UIViewController
{
NSString *imageName;
}
#property (nonatomic, retain) NSString *imageName;
- (void) doSomething;
//IconViewController.m
#implementation AppIconViewController
#synthesize imageName;
NSNumber *iconWidth;
- (void)loadView
{
[super loadView];
UIImageView *iconImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imageName]];
iconWidth = [NSNumber numberWithFloat:iconImage.bounds.size.width];
[iconImage release];
NSLog(#"iconWidth: %f", [iconWidth floatValue]);
}
- (void) doSomething
{
NSLog(#"iconWidth: %f", [iconWidth floatValue]);
}
In another view controller, I'm instantiating several instances of these IconViewControllers and passing different sized images to them:
AppIconViewController *appIcon1 = [[AppIconViewController alloc] initWithNibName:nil bundle:nil];
appIcon1.imageName = #"Image65PXWide.png";
[self.view addSubview:appIcon1.view];
AppIconViewController *appIcon2 = [[AppIconViewController alloc] initWithNibName:nil bundle:nil];
appIcon2.imageName = #"Image105PXWide.png";
[self.view addSubview:appIcon2.view];
Okay, the weirdness is that when I'm creating these, I'm getting logs back that are accurate...appIcon1 logs "iconWidth: 65.0" and appIcon2 logs "iconWidth: 105.0". But when I call:
[appIcon1 doSomething];
...my log is "iconWidth:105.0".
Why is the data in the first instance reflecting the data in the second instance? What am I missing?
EDIT:
I know that if I declare iconWidth in the header and synthesize it as a property, that it will work. So what I'm wondering is how to make a private version of it persist. Because I tried retaining the NSNumber with:
iconWidth = [[NSNumber numberWithFloat:iconImage.bounds.size.width] retain];
...and it still doesn't work. Does it have to be synthesized and public?
EDIT #2:
Okay, so I figured out that once I declare iconWidth in my header, it works just fine, and I don't have to synthesize it so it keeps it private. Not sure why exactly it won't work if declared in the implementation file - does anyone have any insight into why and if there's any purpose in declaring variables at the top of an implementation but not in the header? Just curious now more than anything.
Synthesizing doesn't make anything private. It just generates getter/setter methods according to declared properties.
By placing iconWidth in the implementation, outside of any methods, it's essentially a class-level variable. So it gets overwritten by the last thing that writes to it. You already have imageName declared in the interface, so why not just put iconWidth there as well (instance variables are private by default)?
In your method doSomething, you are assuming iconWidth is set up properly.
However, iconWidth is created as an autorelease object in loadView method, so when loadView finishes, the main loop will release iconWidth and you are getting random values.
To fix this you have to retain iconWidth so you can use it in other methods
iconWidth = [[NSNumber numberWithFloat:iconImage.bounds.size.width] retain];
As a general rule, method that doesn't start with init will return autorelease object, so you have to be careful how you instantiate an object and whether you need to call retain on it.

The right way to hand over an object to a view?

i'm a bit new to iphone development. I made it to develop a nice App which loads XML Data from a feed, displays this data in a UITableView and if a user taps a row there should be a detail view which displays the data.
Thats where i got stuck a little bit. It's not clear for me how to hand over the data of the entry selected by the user to my detail view. The Detail-View is called via presentModalView...
I thought about:
Calling a "setDetails:(PostingData *)myPosting" function of the viewController of my detail view.
presenting the detailView to the user by calling presentModalViewAnimated.
The view is presented, but the setDetails: function crashes without any output to the debugger console.
MY QUESTION:
What is the right way to hand over Data (in custom objects as instance of a self written class) from my view Controller to a View Controller which should display detail data.
Any hint or help is appreciated. I can't pay you for your help, but i'm on my way becoming better and then helping others too :-).
Method 1: Pass it in custom init method
In your Header File declare a property
#property (nonatomic, retain) id myDataObject;
And in your implementation use a custom init like this
-(id)initCustom:(id)myObject;
if(self = [super init]) {
myDataObject = [myObject retain];
}
return self;
}
Method 2: Use a property
Use #property in your Header
and #synthesize in your .m Implementation File
[CustomUIViewController* newViewController = [[CustomUIViewControlleralloc] init];
newViewConroller.myDataObject = myObject;
[view addSubview:newViewController.view];
[newViewController release];
define the custom object in your class. #property(nonatomic, retain) MyClass * myClass;
load the feed into a NSMutableDictionary and provide that to your class
[YOUR_VIEW_CONTROLLER *yourViewController = [[YOUR_VIEW_CONTROLLER alloc] init];
yourViewController.PROPERTY_DEFINED_BEFORE = yourObject;
[view addSubview:yourViewController.view];
[yourViewController release];
cheers

Passing a Property to a function and setting the value to be retained

I have two properties setup as ViewControllers that each use different NIB file. (Male and Female Models, will function the same but are setup visually different.) I want to have one function to create the ViewController based on the NIB Name and ViewController I pass in.
What's happening is the ViewController property is not being retained. If I add the actual property name within the function and set it, the viewController is set and retains the ViewController. Here is what I have in the .m file (Only showing what is needed to get help on.) I've kept in the two comment lines that I tried to do determine where the problem was.
#synthesize femaleModelViewController;
#synthesize maleModelViewController;
- (void) loadModelViewControllerWithModelType:(NSString*) model ModelView:(ModelViewController *)modelViewController {
ModelViewController *viewController = [[ModelViewController alloc] initWithNibName:model bundle:nil];
// [self setFemaleModelViewController:viewController]; // I don't want to set the property here, I want to be able to pass it as an argument.
modelViewController = viewController;
// [modelViewController retain]; // I even tried to retain it do see if would but it doesn't.
[viewController release];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self loadModelViewControllerWithModelType:#"FemaleModel" ModelView:femaleModelViewController];
[self loadModelViewControllerWithModelType:#"MaleModel" ModelView:maleModelViewController];
}
In the .h file my Properties are setup like so:
#property (nonatomic, retain) ModelViewController *femaleModelViewController;
#property (nonatomic, retain) ModelViewController *maleModelViewController;
Are you trying to assign a new ModelViewController to maleModelViewController and femaleModelViewController? If so, you're going about it the wrong way.
Frankly, I'd do away with the loadModelViewControllerWithModelType:modelView: method altogether. All you would need to do in viewDidLoad is this:
maleModelViewController = [[ModelViewController alloc] initWithNibName:#"MaleModel"];
femaleModelViewController = [[ModelViewController alloc] initWithNibName:#"FemaleModel"];
(This assumes that maleModelViewController and femaleModelViewController are the instance variables backing the properties of the same name.)
When you pass in maleModelViewController and femaleModelViewController, you're not passing a reference to those variables, you're passing their values. Since they haven't been initialized, all you're doing is passing in nil. To do what you're trying to do, you'd need to pass a pointer to the variables (i.e. declare the parameter as ModelViewController **, pass it in as &maleModelViewController and &femaleModelViewController and assign it using *modelViewController = viewController. If you're used to using pass-by-reference friendly languages like C# or Java, you should read up on how it works in C. (The rules are the same in Objective-C as in C).
HOWEVER, that is still complete overkill for what you're trying to do here.
Also, your code would still not work because you turn around and release viewController. This would cause it to be immediately deallocated, since the only reference you had to it came from when you alloced it. You would be assigning a dead reference that would crash your program as soon as you tried to use it.