ModalViewController not presenting on button press - objective-c

I have this ViewController with on it a UIButton. This button fires a method and this should present a modalVC in his place. Yet for some reason it's not working anymore. I've been using the same code before without any issues but yet it bugs me.
-(void)showModalVC //the method that's being fired by the button.
{
NSLog(#"modalVC to create a table"); //this log is being printed so the button fires as proper.
self.myModalVC = [[MyModalViewController alloc] init]; //a local var gives same results.
self.myModalVC.dismissDelegate = self; //the delegate is handled as proper.
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:self.myModalVC];
//navController.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:navController animated:YES];
[self.myModalVC release];
[navController release];
}
What could be a reason for a ModalVC not to pop over my current view from where ever it is called?
I've been using this very same method before (in other projects in other contexts) so I'm dazzled it hasn't been working yet. The method is fired and it passes every line of code without crash.
If you have an idea. post it here.
Thanks.

The first thing I thought of is that you are creating a leaked object at this line:
self.myModalVC = [[MyModalViewController alloc] init];
self. will retain myModalVC, alloc will also retain it and you are probably releasing it only in dealloc method.
In all other means the code looks quite working. But looking at how you are using self. prefix, maybe you've got a memory issue somewhere else in your application? Try reading about properties and accessor methods.

-(void)showModalVC
{
self.myModalVC = [[ModalVC alloc] init];
self.myModalVC.dismissDelegate = self;
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:self.myModalVC];
navController.modalPresentationStyle = UIModalPresentationFormSheet; //or something similar, this one is used on an iPad
UILabel *navTopItemTitle = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 300, 44)];
navTopItemTitle.text = #"Modal shizzle";
navTopItemTitle.backgroundColor = [UIColor clearColor];
navTopItemTitle.textColor = [UIColor whiteColor];
navTopItemTitle.textAlignment = UITextAlignmentCenter;
[navController.navigationBar.topItem setTitleView:navTopItemTitle];
[self presentModalViewController:navController animated:YES];
[self.addTabViewController release];
[navController release];
}
Problem solved.

Related

Adding UIBarButtonItem's to a UIToolbar

I need to add buttons to the UIToolbar of a UINavigationController, which is also my root. I want the UIToolbar to appear when a specific UIViewController is shown. Therefore, I placed this code in my viewDidLoad method of my UIViewController subclass:
UIBarButtonItem* item = [[UIBarButtonItem alloc] initWithTitle:#"Title" style:UIBarButtonItemStyleBordered target:self action:#selector(doSomething)];
item.width = 300;
item.tintColor = [UIColor whiteColor];
UIBarButtonItem* item2 = [[UIBarButtonItem alloc] initWithTitle:#"Title2" style:UIBarButtonItemStyleBordered target:self action:#selector(doSomething)];
NSMutableArray* theItems = [self.navigationController.toolbar.items mutableCopy];
[theItems addObject:item];
[theItems addObject:item2];
[self.navigationController.toolbar setBarStyle:UIBarStyleBlackOpaque];
[self.navigationController setToolbarHidden:NO animated:YES];
[self.navigationController setToolbarItems:theItems animated:NO];
//self.navigationController.toolbarItems = theItems; // Tried both
UILabel* label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 20)];
label.text = #"kjhdkjhadsda";
[self.navigationController.toolbar addSubview:label];
This only shows the UILabel in the correct position, nothing else appears. The UILabel is useless for me, it is just a test. I also tried to allocate a new array instead of copying the one from the component. Ignore the missing releases, this is only test code.
I read many questions about this but no answer seem to help making it work. Any idea what might not be ok in this code?
Seems that you are trying make mutable copy of nil in line
[self.navigationController.toolbar.items mutableCopy];
By default method navigationController.toolbar.items nas no items and returns nil
Update
Method - (void)setToolbarItems:(NSArray*)toolbarItems animated:(BOOL)animated does nothing if you send it to UINavigationController. You need to set toolbar items to that controller who is managed by a navigation controller. This line will make your buttons visible:
[self setToolbarItems:theItems animated:NO];

Animating Picker in + Done button + TextField updating

Hi Can anyone help me out with this, ive been looking at alot of the previous questions on this subject and they seem a little complicated. I want to setup a picker that animates in on the touch of a text field which has an IBOutlet called locationField.
I dont want to add the picker or toolbar and buttons in my story boards I would rather do it programatically.
So far I have:
- (void)viewDidLoad
{
//populate picker arrays
locationPickerArray = [[NSArray alloc] initWithObjects:#"1",#"2",#"3",#"4",#"5", nil];
actionSheet = [[UIActionSheet alloc] initWithTitle:#"" delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
[actionSheet showInView:self.view];
UIToolbar *pickerToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0,480,32)];
[pickerToolbar sizeToFit];
pickerToolbar.barStyle = UIBarStyleBlackTranslucent;
NSMutableArray *barItems = [[NSMutableArray alloc] init];
UIBarButtonItem *cancelBtn = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonSystemItemCancel target:self action:#selector(cancel_clicked:)];
[barItems addObject:cancelBtn];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
[barItems addObject:flexSpace];
UIBarButtonItem *doneBtn = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStyleDone target:self action:#selector(done_clicked:)];
[barItems addObject:doneBtn];
[pickerToolbar setItems:barItems animated:YES];
[actionSheet addSubview:pickerToolbar];
UIPickerView *picker = [[UIPickerView alloc] init];
picker.frame = CGRectMake(0, 44, 320, 216);
picker.delegate = self;
picker.dataSource = self;
picker.showsSelectionIndicator = YES;
[actionSheet addSubview:picker];
}
-(void)done_clicked:(id)sender
{
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
-(void)cancel_clicked:(id)sender
{
[actionSheet dismissWithClickedButtonIndex:0 animated:YES];
}
I have a few questions about this, it crashes on:
* Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[DetailsScreenViewController
numberOfComponentsInPickerView:]: unrecognized selector sent to
instance 0xb505be0'
What does this mean?
My final question is how can I populate this picker and assign it to popup when the iboutlet I created earlier is clicked (location field).
Thank you
The reason for your crash is that you've assigned an instance of DetailsScreenViewController to be the dataSource and delegate of a UIPickerView without actually implementing the methods for these protocols. The assignment takes place here:
picker.delegate = self;
picker.dataSource = self;
The specific crash is telling you that you haven't implemented numberOfComponentsInPickerView:, part of the UIPickerViewDataSource protocol. You should have gotten a compiler warning about this actually. Learning to use those warnings can be really helpful! Anyways, to fix it, provide implementations for all of the required methods on both protocols. The details of the implementations will depend on the needs for your app. If you still need help with details let me know.
Regarding your second question, I guess putting a UIPickerView inside a UIActionSheet is a thing now. I've never had a need to do it before, but here is a SO question with a lot of sample code for some background, not sure if you've read that one yet. But I think you'd just want to wait for the time you actually want to show the picker to call
[actionSheet showInView:self.view];
I think you can do this in a UITextFieldDelegate method, there are probably other ways. I'm going to try to do some experiments with that later and update this post.
EDIT:
If you assign your view controller as the delegate of whatever text field you're interested in, then you can implement this UITextFieldDelegate method:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[actionSheet showInView:self.view];
return NO;
}
END EDIT
Hope this helps, and let me know if you have any questions.

its not navigating to the class

I am writing the following code in a button click event and i am trying to navigato the class PDFReaderViewController, but on click of the button its not navigating, can anybody tell me y
UINavigationController *addNavigationController;
PDFReaderViewController *avController = [[PDFReaderViewController alloc] initWithNibName:nil bundle:nil];
if(addNavigationController == nil)
{
addNavigationController = [[UINavigationController alloc] initWithRootViewController:avController];
addNavigationController.navigationBar.tintColor = [UIColor blackColor];
addNavigationController.navigationBar.alpha=0.7f;
addNavigationController.navigationBar.translucent=YES;
[self.navigationController presentModalViewController:addNavigationController animated:YES];
}
What you are actually looking for?
In your code you are trying to present a navigationController from another navigation controller.
To present a vieController as a modelViewController you don't need a custom NavigationController.You can present it simply by:
PDFReaderViewController *avController = [[PDFReaderViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController presentModalViewController:avController animated:YES];
[avController release];
Class *obj=[Class alloc];
[self.view addSubview:obj.view];
You can use this for navigating Class.

Creating a common UIToolbar helper file and methods for Objective C

I have build a view with a UIToolbar which is working great.
This toolbar will be appearing right across the app, and right now I am copy/pasting the code into lots of different files.
I do not want to repeat myself, and am looking to create a helper file that will include the toolbar setup and the methods linked to the toolbar in every file I need.
I've tried putting the following code into a .h .m file and inheriting from UIView, but there is a problem because there is a reference to self.navigiationItem
Is there a way that I can create a common Objective C file that will have all the code and methods I want to use?
Thanks.
- (void)viewDidLoad
// ...
// appears in viewDidLoad
// ---- TOOLBAR -----------//
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, 100.0, 44.01f)];
//[toolbar setBackgroundColor:[UIColor blackColor]];
//[toolbar setTintColor:[UIColor redColor]];
//[toolbar.layer setBorderColor:[[UIColor redColor] CGColor]];
// Bar buttons
UIBarButtonItem *barReloadBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:#selector(btnReload:)];
[barReloadBtn setStyle:UIBarButtonItemStyleBordered];
// Profile bar button
UIImage *image = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"111-user" ofType:#"png"]];
UIBarButtonItem *barProfileBtn = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStyleBordered target:self action:#selector(btnProfile:)];
// Button array
NSMutableArray *buttons = [[NSMutableArray alloc] init];
[buttons addObject:barProfileBtn];
[buttons addObject:barReloadBtn];
[toolbar setItems:buttons];
// Set nav items
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:toolbar];
// memory cleanup
[image release];
[buttons release];
[barReloadBtn release];
[barProfileBtn release];
[toolbar release];
// ---- /TOOLBAR -----------//
}
#pragma mark - IBActions
-(IBAction) btnProfile:(id)sender
{
UserProfileVC *userProfileVC = [[UserProfileVC alloc] initWithNibName:#"UserProfileVC" bundle:[NSBundle mainBundle]];
UINavigationController *tmpNavCon = [[UINavigationController alloc] initWithRootViewController:userProfileVC];
[self.navigationController presentModalViewController:tmpNavCon animated:YES];
[tmpNavCon release];
[userProfileVC release];
}
-(IBAction) btnReload:(id)sender
{
NSLog(#"Not done yet");
}
navigationItem is a property of UIViewController, not UIView. If you've got common functionality like this, I would inherit from UIViewController, add your custom logic to viewDidLoad (or wherever is appropriate) and then inherit your view controllers from that class. Just make sure you call [super viewDidLoad] from your subclasses' implementations of viewDidLoad.

Navigation Control Problem

I am using some methods to load a new .xib and go back to the main menu. However after about five time it crashes by using too much memory. I need to be able to go back to the main menu and to the game many times. Any other methods I should use for the navigation controls.
Main Menu part:
GameViewController* game = [[GameViewController alloc initWithNibName:#"GameViewController" bundle:nil];
[self.navigationController pushViewController:game animated:NO];
Game part to return to main menu:
[self.navigationController popViewControllerAnimated:NO];
Here is the viewdidLoad
{
- (void)viewDidLoad {
[super viewDidLoad];
[self StartTimer];
TotalSeconds = 0;
GameCenterTotalSeconds = 0;
timeSec = 0;
timeMin = 0;
Background = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 480, 320)] autorelease];
Background.image = [UIImage imageWithContentsOfFile:[ [ NSBundle mainBundle] pathForResource:#"Background" ofType:#"png"]];
[self.view addSubview:Background];
timeLabel.textColor = [UIColor redColor];
[self.view addSubview:timeLabel];
NumberLabel = [[[UIImageView alloc] initWithFrame:CGRectMake(0, -4, 60, 70)] autorelease];
NumberLabel.image = [UIImage imageWithContentsOfFile:[[ NSBundle mainBundle] pathForResource:#"Number" ofType:#"png"]];
[self.view addSubview:NumberLabel];
QuestionNumber = [[[UILabel alloc] initWithFrame:CGRectMake(23, 17, 20, 20)] autorelease];
QuestionNumber.text = #"1";
QuestionNumber.textColor = [UIColor redColor];
QuestionNumber.backgroundColor = [UIColor clearColor];
[QuestionNumber setFont:[UIFont fontWithName:#"Marker Felt" size:30]];
[self.view addSubview:QuestionNumber];
numberLives = 1;
appDelegate = (OppositeMoronTestAppDelegate *)[[UIApplication sharedApplication]delegate];
musicButton = [[[UIButton buttonWithType:UIButtonTypeCustom] retain] autorelease];
musicButton.frame = CGRectMake(5, 283, 35, 35);
musicButton.backgroundColor = [UIColor clearColor];
if (appDelegate.shouldPlayMusic == YES) {
UIImage *Image = [UIImage imageWithContentsOfFile:[[ NSBundle mainBundle] pathForResource:#"MusicOn" ofType:#"png"]];
[musicButton setBackgroundImage:Image forState:UIControlStateNormal];
[musicButton addTarget:self action:#selector(TurnMusicOff) forControlEvents:UIControlEventTouchUpInside];
} else {
UIImage *Image = [UIImage imageWithContentsOfFile:[[ NSBundle mainBundle] pathForResource:#"MusicOff" ofType:#"png"]];
[musicButton setBackgroundImage:Image forState:UIControlStateNormal];
[musicButton addTarget:self action:#selector(TurnMusicOn) forControlEvents:UIControlEventTouchUpInside];
}
[self.view addSubview:musicButton];
[self showQuestion1];
}
}
try autorelease on your view controller:
GameViewController* game = [[[GameViewController alloc initWithNibName:#"GameViewController" bundle:nil] autorelease];
The navigation controller will take ownership of the view controller passed to it, so you don't have to keep a reference to it. But you can't keep allocating GameViewControllers over and over without releasing them. autorelease is useful for that. You could also release it after you've passed it to the navigation controller if you prefer:
GameViewController* game = [[GameViewController alloc initWithNibName:#"GameViewController" bundle:nil];
[self.navigationController pushViewController:game animated:NO];
[game release];
game = nil;
EDIT:
So if you're already releasing the game object, then it must be a memory leak within the GameViewController class itself.
Annything you alloc, copy or retain in your GameViewController class you're supposed to release in the dealloc method (and maybe also in the viewDidUnload method if you're alloc/copy/retaining in the viewDidLoad method).
The iOS Memory Management Programming Guide might be helpful if you want to get into more detail.
If you want to post the relevant code from the GameViewController class, I'm sure someone will be able to help you pin down the memory leak.
You can also try the Leaks tool in Instruments
EDIT 2:
I'm assuming you have several IBOutlets connected to properties in your GameViewController class...
don't know if you're already doing this, but in your viewDidUnload method AND on your dealloc method you have to set all of these IBOutlets properties to nil in order to release them, like so:
- viewDidUnload
{
//... whatever comes before
self.timeLabel = nil;
self.NumberLabel = nil;
//... etc
}
- dealloc
{
//... whatever comes before
self.timeLabel = nil;
self.NumberLabel = nil;
//... etc
[super dealloc];
}
In general, if you have any properties declared with retain, that means that when you set that property the object will be retained. If you set that property to nil, the object that was there will be released for you. So any properties with the retain keyword should be set to nil (or the backing ivar released).