I'm created Class and it's add to the current view with non arc project. After that i'm releasing it as this.
TestViewController *tView=[[TestViewController alloc] initWithNibName:#"TestViewController" bundle:nil];
tView.view.frame=CGRectMake(10, 10,tView.view.frame.size.width , tView.view.frame.size.height);
[self.view addSubview:tView.view];
[tView release];
I added button to the TestViewController and when pressed it just crash and view this message from console.
-[TestViewController performSelector:withObject:withObject:]: message sent to deallocated instance
Anyone can explain the reason for that?
When you call [tView release]; TestViewController's dealloc method will automatically get called. And Objects of this class will be released. So Probably you have released that button in dealloc. That's why your app is crashing.
This is not the right way to do it.
You should create a custom view and add that view to self.view instead of adding viewcontroller's view.
Currently, you had declared TestViewController instance as local. So, that only it is getting crash while accessing the controls which are there in the instance.
Declare TestViewController instance in class level(ivar) and then use it.
Obviously, the target of your button is tView. [tView dealloc] is called after [tView release] as its retainCount decrease to 0.
You should declare tView as a private member variable, such as _tView, and call [_tView release] in your view controller's dealloc function.
#interface **
{
TestViewController *_tView;
}
if(!_tView){
_tView=[[TestViewController alloc] initWithNibName:#"TestViewController" bundle:nil];
}
_tView.view.frame=CGRectMake(10, 10,tView.view.frame.size.width , _tView.view.frame.size.height);
[self.view addSubview:_tView.view];
In iOS 5.*, custom container view controllers is supported. (http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html )
You can write code like this:
TestViewController *tView=[[TestViewController alloc] initWithNibName:#"TestViewController" bundle:nil];
tView.view.frame=CGRectMake(10, 10,tView.view.frame.size.width , tView.view.frame.size.height);
[self.view addSubview:tView.view];
[self addChildViewController:tView];
[tView didMoveToParentViewController:self];
[tView release];
you can use below code
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.yourViewController addSubview:button];
self.viewController means you have define your viewcontroller in .h file and then use you instance of the view controller to add your button.
then you can release your viewController [ViewController Release];
Related
I am using a custom Switch view controller and you would hope when switching between different views the "view did load" function or "view did finished loading" functions run but they do not.
Here what I am using:
- (IBAction)gotoKeyboardViews:(id)sender
{
YellowViewController *yellowController =
[[YellowViewController alloc]
initWithNibName:#"YellowViewController"
bundle:nil];
self.yellowViewController = yellowController;
[yellowController release];
[buttonKeyboard removeFromSuperview];
buttonStart = [UIButton buttonWithType:UIButtonTypeRoundedRect];
buttonStart.frame = CGRectMake(117,413, 103, 37);
[buttonStart setTitle:#"Restart" forState:UIControlStateNormal];
[buttonStart addTarget:self action:#selector(gotoBlueView:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:buttonStart];
[blueViewController.view removeFromSuperview];
[self.view insertSubview:yellowViewController.view atIndex:0];
}
gotoKeyboardViews suppose to switch the views To YellowView From BlueView...But I think I am a little bit off about implementing the navbar. Please don't tell me to go with the navbar because I don't like their rigidness in design.
The viewWillAppear method is executed as soon as the view gets active again. Maybe that's the hook you are searching?
Reference: Apple UIViewController Class Reference
those methods are only called when the nib file is loaded or the if you've override loadView. They will not get called again unless a new view controller is instantiated.
I have an application in which I need to be able to update what buttons may appear on the home screen and have elected to use core data to allow me to update the controlling property via XML. The core data seems to be working well and updating, and the buttons are being created, however, for some reason, the selector doesn't seem to be retained as it crashes every time I click on the button. The error log doesn't say anything - except one time when it did say "unrecognized selector sent to instance". Here is the method I use to create the buttons:
- (void)setUpNavigationButtons {
int i = 0;
for (Features *myFeature in self.features) {
CGRect buttonRect = [self makeFeatureButtonFrame:[self.features count] withMember:i];
UIButton *aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[aButton setFrame:buttonRect];
[aButton addTarget:self action:#selector(buttonTouched:) forControlEvents:UIControlEventTouchUpInside];
[aButton setTitle:[NSString stringWithFormat:#"%#",myFeature.name] forState:UIControlStateNormal];
[self.view addSubview:aButton];
i++;
}
}
Here is the the selector method, in the same view controller class:
- (void)buttonTouched:(id)sender{
NSLog(#"feature selected");
}
Any help is much appreciated. Please let me know if more of the code is required to ascertain anything meaningful. I don't want to ask folks to read through a mountain of it if only a molehill is required.
UPDATE: 4/27/2011
In response to the comments in the checked answer below, I am posting the code that launches the view controller. I've not had a problem with this in the past, but it's entirely possible I've picked up some bad technique in here. This is from the method application:didFinishLaunchingWithOptions method in the AppDelegate. Anyway, here is the code:
UINavigationController *navigationController = [[[UINavigationController alloc] init] autorelease];
HomeViewController *root = [[HomeViewController alloc] initWithNibName:#"HomeViewController" bundle:nil];
root.title = companyName;
root.context = [self managedObjectContext];
[navigationController pushViewController:root animated:NO];
[window addSubview:navigationController.view];
[root release];
[self.window makeKeyAndVisible];
return YES;
Disclaimer; I'm guessing here.
Perhaps your controller isn't sticking around in memory, and it needs to be retained?
[aButton addTarget:[self retain] action:#selector(buttonTouched:) forControlEvents:UIControlEventTouchUpInside];
NOTE: THE ABOVE CODE IS BAD. It merely identified the problem in the original question. See comments below for details.
That code above is probably bad if it fixes the issue, unless each button also sends [target release] when being destroyed.
Also, you should use IBAction instead of void for button actions:
- (IBAction)buttonTouched:(id)sender{
NSLog(#"feature selected");
}
I'm creating a simple modal ViewController. I'm creating a nib with a button and on that button press calling a method to display modal viewController in which I'm creating the viewController and a button inside it like this.
UIViewController *modalViewController = [[UIViewController alloc]initWithNibName:nil bundle:nil];
modalViewController.view.backgroundColor = [UIColor redColor];
modalViewController.;
UIButton *btnDismissViewController = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnDismissViewController.frame = CGRectMake(60, 160, 150, 50);
[btnDismissViewController setTitle:#"DISMISS" forState:UIControlStateNormal];
[btnDismissViewController addTarget:self action:#selector(dismissViewCOntroller) forControlEvents:UIControlEventTouchUpOutside];
btnDismissViewController.backgroundColor = [UIColor grayColor];
[modalViewController.view addSubview:btnDismissViewController];
[self presentModalViewController:modalViewController animated:YES];
This view is appearing properly but after pressing the button on modalViewController, the target method for dismissing the modalViewController isn't called. I'm definitely missing something obvious but not getting what. Can anybody please help?
Thanx in advance.
I agree with Ole's comment... additionally, make sure you are dismissing it within your dismissViewCOntroller method similar to this:
[self.parentViewController dismissModalViewControllerAnimated:YES];
I think there might be a typo in your code, dismissViewCOntroller seems like it should be dismissViewController, but maybe that was intentional, and the control state should be UIControlEventTouchUpInside.
I was wondering if anyone knew of any good online resources/tutorials for creating views and controllers programatically rather than via the interface builder. Everything I have looked at uses the interface builder and the created nibs, while the IB is ok I would like to have the option of developing these manually (both for practical reasons and get a good understanding of how it all fits together rather than the superficial one you get from dragging and dropping things).
My background is in java and I'm finding it slow and frustrating using the interface builder to develop views the way I would sometimes do them in Java, i.e. either
generate the source programatically from a domain model and then tweak the result if requried
use some meta-data and/or reflection and dynamically add the controls to the view
Also, once I have created a view is there anyway I can add it to the interface builder to make it available to use as a sub view on another view?
Thanks, Vic
The Interface Builder method creates "freeze-dried" objects that are re-created at runtime when you initialize the object from the NIB. It still does the same alloc and init stuff, using NSCoder objects to bring the objects in to memory.
If you want to have a view controller based on a particular NIB, you can then override the default init method and init it based on the NIB for that view controller. For example:
#implementation MyViewController
-(id) init {
if (self = [super initWithNibName:#"MyViewController" bundle:nil]) {
//other setup stuff
}
return self;
}
And when you want to display the MyViewController, you would simply call something like this:
- (void) showMyViewController {
MyViewController *viewController = [[[MyViewController alloc] init] autorelease];
[self presentModalViewController:viewController animated:YES];
}
Now, if you want to create your view manually instead of in Interface Builder, you don't have to change your -showMyViewController method at all. Get rid of your -init override, and instead override the -loadView method of your MyViewController to create it programmatically:
- (void) loadView {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(320,460)];
self.view = view;
[view release];
//Create a button
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton addTarget:self action:#selector(pressedButton) forControlEvents:UIControlEventTouchUpInside];
[myButton setTitle:#"Push Me!" forState:UIControlStateNormal];
myButton.frame = CGRectMake(100,230,80,44);
[self.view addSubview:myButton];
}
This example shows how to create the view and add a button to it. If you want to keep a reference to it, declare it the same way you would if you were using a NIB (without the IBOutlet/IBActions) and use self when assigning it. For example, your header might look like this:
#interface MyViewController : UIViewController {
UIButton *myButton;
}
- (void) pressedButton;
#property (nonatomic, retain) UIButton *myButton;
#end
And your class:
#implementation MyViewController
#synthesize myButton;
- (void) loadView {
//Create the view as above
self.myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[myButton addTarget:self action:#selector(pressedButton) forControlEvents:UIControlEventTouchUpInside];
[myButton setTitle:#"Push Me!" forState:UIControlStateNormal];
myButton.frame = CGRectMake(100,230,80,44);
[self.view addSubview:myButton];
}
- (void) pressedButton {
//Do something interesting here
[[[[UIAlertView alloc] initWithTitle:#"Button Pressed" message:#"You totally just pressed the button" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK",nil] autorelease] show];
}
- (void) dealloc {
[myButton release];
[super dealloc];
}
I had the same issue a couple of months ago when I wanted to do all the iPhone development inside Emacs. To make a long story short: I'm not developing for the iPhone anymore :)
I'd still suggest you to check my question and some helpful answers here.
I typically don't use Interface builder too much for iPhone development. Usually I will create a view controller in code like this
MyUIViewControllerSubclass *controller = [[MyUIViewControllerSubclass alloc] initWithNibName:nil bundle:nil];
controller.someProperty = myModel;
[self presentModalViewController:controller];
[controller release];
Or something along those lines. Typically I create a subclass of UIViewController and that's where I layout my views and such. The views are subclasses of UIView (either things Apple provides like UIButton etc, or something I've created myself). If you read up on both UIViewController and UIView you should get a pretty good idea of how it works.
I have created a UIView and added label to it and latter assign it to Controller.
Now whenever I click on my View it shows me "EXC_BAD_ACCESS”.
Below is my code.
//create a UIView in App Delegate
UIView *viewPtr = [[[UIView alloc] initWithFrame:frmRect] autorelease];
//created a Button and added to UIView
UIButton *btnPointer = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnPointer.frame = cgframe; // provides both a position and a size
[btnPointer setTitle:btnLabelText forState:UIControlStateNormal];
[btnPointer addTarget:self action:#selector(generate:) forControlEvents:UIControlEventTouchUpInside];
[viewPtr addSubview:btnPointer];
//Now need to add this UIView to a controller
viewController.view = viewPtr;
I am able to display the button on the Form but when I click on the form or the button I get
"EXC_BAD_ACCESS”.
You should create the view in the .m file of your view controller like this.
- (void)loadView
{
UIView *viewPtr = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
//created a Button and added to UIView
UIButton *btnPointer = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnPointer.frame = cgframe; // provides both a position and a size
[btnPointer setTitle:btnLabelText forState:UIControlStateNormal];
[btnPointer addTarget:self action:#selector(generate:) forControlEvents:UIControlEventTouchUpInside];
[viewPtr addSubview:btnPointer];
//Now need to add this UIView to a controller
self.view = viewPtr;
[viewPtr release];
}
Hope this helps.
Thanks,
Madhup
Instead of use the autorelease
UIView *viewPtr = [[[UIView alloc] initWithFrame:frmRect] autorelease];
Create the UIView *viewPtr on the .h file, and only do the release in the dealloc method
So, you will have the declaration on your .h file
UIView *viewPtr;
And you .m file will be with the following lines, when you instantiate the viewPtr in the same place where you was doing previously, but without the autorelease, and the release on the dealloc method as follow:
viewPtr = [[UIView alloc] initWithFrame:frmRect];
.
.
.
.
.
.
.
.
- (void)dealloc {
[viewPtr release];
[super dealloc];
}
The autorelease is the main problem in your code, because when you do this, your UIView won't respond to any event.
Cheers,
VFN
What is self in [btnPointer addTarget:self ... ? Is generate: called? Have you tried debugging there?
As vfn says, this you get the error because you release the view too early. The question I would be asking is why is this case different?
Normally in an assignment like this:
viewController.view = viewPtr;
The viewPtr is retained and you would be correct to release it yourself. But look at the definition:
#property(nonatomic, retain) UIView *view
This means that any value is simply assigned and not automatically retained.