The layout...
I have a UIToolbar that loads a view with several buttons. One of those buttons, on the onpress should display a popup.
It does. However, the popup seems to open up at 0,0.
-(IBAction)FilterButtonPressed:(id)sender
{
if (_FilterViewController == nil) {
self.FilterViewController = [[[FilterViewController alloc] initWithStyle:UITableViewStylePlain] autorelease];
_FilterViewController.filterViewDelegate = self;
self.FilterViewPopover = [[UIPopoverController alloc] initWithContentViewController:_FilterViewController];
}
NSLog(#"Button...: %#",NSStringFromCGRect(self.FilterButton.frame));
[self.FilterViewPopover presentPopoverFromRect:self.FilterButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
The NSLog reads:
Button...: {{0, -4.38184}, {0, 4.76182e-39}}
which is... just weird..
Any suggestions as to why the FilterButton doesn't know where it is?
Any suggestions as to why the FilterButton doesn't know where it is?
Looks like it's uninitialized / not properly initialized. Are all your outlets set up properly? Whenever "my xyz object is not behaving properly" happens, checking your outlets is usually the first order of business (note that the action can be hooked up from a button, but your link to the button from your class may not be. Try printing the state from the "sender" cast to "UIButton *".
Related
My application is freezing with a reason that I could not figure out, it does not crash but it freezes.
basically what I did was having another view inside my view that is hidden at first place, after when I click a button this view will be appeared and it includes a UItextfield and a UIPickerView. the pickerview data is updating while I edt the UItextfield and I select one of the values from picker view then basically press addButton, when I add thi whole view will be hidden again and the selected value of the pickerview will be added another UITextfield in the main view.
when I do this first time it works fine. it sets the value of the UI textfield which is on the main view to the correct value. but when I try to change it, get that view unhidden and select another value in the pcikerview and press on addButton again the application freezes. No crash appears.
I want to inform you about this the value of the UITextfield on the main view is changing I checked it on the logs. and the method that do the clicking action completely works. But it freezes.
I couldnt figure it out, I need some help :)
EDIT:
I figure out that the UITextField on the main view cause this freeze, when I set the text
[myTextfield setText:#"somethng"];
the UI freeze. when I comment this out it works pretty fine. But It works fine at first time. does not work on the second time.
Any help will be appreciated.
EDIT 2 (I added some code):
-(IBAction)addButtonClicked:(id)sender
{
leftBarButton = [[UIBarButtonItem alloc] initWithTitle:#"Done" style:UIBarButtonItemStylePlain target:self action:#selector(pickerViewDoneClicked:)];
[[self.navigationController.navigationBar.items objectAtIndex:0] setLeftBarButtonItem:leftBarButton];
[self.pickerContainer setHidden:NO];
}
-(IBAction)pickerViewDoneClicked:(id)sender
{
[[self.navigationController.navigationBar.items objectAtIndex:0] setLeftBarButtonItem:nil];
NSLog(#"%#", self.myTextField);
NSLog(#"old val %#", self.myTextField.text);
// the text field on the main view.
[self.myTextField setText: selectedText];
NSLog(#"new val %#", self.myTextField.text);
[self.pickerContainer setHidden:YES];
}
//in picker view source
selectedText = [pickerData objectAtIndex:row];
As I told the first time I add it works fine I can see the value on the textfield
but when I do the same action again and click done the app freezes.
I checked the reference of the textfield before after and no reference missing
I can see the new value and old value as well. but the UI freezes.
Just to be sure: you do not perform any call to UIKit on non-main thread?
I was using this piece of code for padding for my text field,
UIView *paddingView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 15, 20)];
self.myTextField.leftView = paddingView;
self.myTextField.leftViewMode = UITextFieldViewModeAlways;
I am not sure how it effects it but second time I change the text into the textfield I was getting my screen freezed.
Thanks again for any effort to help me.
I have a tab bar app. Under one of the tabs i want a uisegmentedControl in the top navigation view, that controls what view is currently displayed. This is dead easy if i just exchange the view, but i want to do it in a more organized and generic way, by using one uiviewcontroller for each view and exchanging them in the most optimzed way.
i guess step one would be to know exactly what a tabbar controller sends to a navigation controller/view controller when a tab is changed, and work it out from there.
Can any one point me in the right direction?
Some time ago I stumbled upon SegmentsController which I found in this blog entry from red artisan.
I used it in conjunction with a UITabBarController, but without knowing I did it wrong. Not wrong as in "it crashs" or "it doesn't do what i want" but wrong in the sense that I have to forward each UIViewController call (like viewDidAppear, receivedMemoryWarning etc) to the child viewControllers. The app with the wrong code is still in the app store and I never received a complain about it.
But I played around a while and figured out how to use it right. It's a bit of a hassle but imho it's absolutely worth it.
I'll show you the correct version that I have right now, I'm creating the UITabBarController in Interface Builder so I have to change the tab in code. Which introduces another piece of mess, and maybe there is room for improvements. But right now I'm satisfied with this solution.
NSMutableArray *items = [self.tabBarController.viewControllers mutableCopy]; // tabs from tabbar configured in IB
// The two child vc that will appear in the segment control
SomeViewController_iPhone *tvcs = [[[SomeViewController_iPhone alloc] initWithNibName:#"SomeView_iPhone" bundle:nil] autorelease];
SomeOtherViewController_iPhone *tvct = [[[SomeOtherViewController_iPhone alloc] initWithNibName:#"SomeOtherView_iPhone" bundle:nil] autorelease];
NSArray *viewControllers1 = [NSArray arrayWithObjects:tvcs, tvct, nil];
// the nav controller acts as a wrapper around the child viewcontrollers
UINavigationController *navController1 = [[[UINavigationController alloc] init] autorelease];
navController1.tabBarItem.title = NSLocalizedString(#"FirstTab", nil);
navController1.tabBarItem.image = [UIImage imageNamed:#"tabImage1.png"];
navController1.navigationBar.tintColor = [UIColor navBarTintColor];
firstTabSegmentsController = [[SegmentsController alloc] initWithNavigationController:navController1 viewControllers:viewControllers1];
// uses a NSArray category that basically creates a NSArray that has the title properties of the vc in viewControllers1
firstTabSegmentedController = [[UISegmentedControl alloc] initWithItems:[viewControllers1 arrayByPerformingSelector:#selector(title)]];
firstTabSegmentedController.frame = CGRectMake(0, 0, 222, 30);
firstTabSegmentedController.segmentedControlStyle = UISegmentedControlStyleBar;
firstTabSegmentedController.selectedSegmentIndex = 0;
[firstTabSegmentsController indexDidChangeForSegmentedControl:firstTabSegmentedController];
[firstTabSegmentedController addTarget:firstTabSegmentsController action:#selector(indexDidChangeForSegmentedControl:) forControlEvents:UIControlEventValueChanged];
// replace first tab from interface builder with this
[items replaceObjectAtIndex:0 withObject:navController1];
as you see it needs a bit of setup, but in my opinion this solution is better than anything else I've tried throughout the time. I hope I de-NDAed the code correctly.
Edit: Uploaded a sample project: BeautifulColors.zip
Just exchanging the views and keeping up with the current view's viewController is the best way to implement a UISegmentedControl in this regard.
Note: by exchanging the views i mean adding a subview to the current view and removing the old one.
You might be interested in the method below, which is implemented by the UITabBarControllerDelegate
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController;
I'm trying to make a modal view which displays the champion of my app.
there's a NSMutableString variable called champ in modal view,
which is supposed to be updated by returnChamp function in main view.
the champ string is correctly set in main view,
but in modal view, the champ value appears as (null).
In fact, it seems it doesn't even go into the returnChamp function.
so apparently something wrong with my calling or implementing returnChamp,
but I have another function that does the similar, and that works fine.
could anyone please help me?
-(void) mainView{
.....
champ = [[currentPlayers objectAtIndex:playerIndex] retain];
NSLog(#"%#",champ);
modalWinner = [[winner alloc] init];
modalWinner.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:modalWinner animated:YES];
}
- (NSMutableString *) returnChamp{
NSLog(#"returnChamp");
return champ;
}
//in modalWinner
-(void) modalView{
..............
champName = [[NSMutableString alloc] init];
NSLog(#"%#", [(MainViewController *)self.parentViewController returnChamp]);
champName = [(MainViewController *)self.parentViewController returnChamp];
UIImage *champImage = [UIImage imageNamed:champName];
}
self.parentViewController is probably not actually a reference to your object. For some reason, it seems that the framework always insists on setting a UINavigationController as self.parentViewController - even for modals, and to the extent that it will create one if there isn't already one. This is probably going unnoticed because you're casting it to your MainViewController type.
You'll need to find a different way of making your original object available to be communicated with, or perhaps pass the appropriate value to the newly-instantiated controller before you present it.
For example, if you add a champName property to the modal class, you can do:
modalWinner = [[ModalWinnerViewController alloc] init];
modalWinner.champName = myValue; /* Set value before presenting controller */
[self presentModalViewController:modalWinner animated:YES];
There will probably be some code needed to update the UI with this value. The viewWillAppear method of the modal view controller is a good place for this as it is called by the framework immediately before the view is presented.
Note that this property-based approach could be used to keep a reference to your intended parent object, as well. And see here for a different approach to solving a similar problem.
Okay, here is my issue: My app has a display of categories in the tab bar at the bottom of the iPhoneOS screen. This only allows 5 categories before it presents the MORE button. I have over 25 (please do not answer this by saying: "Rethink your application...etc" -- that was rudely said before. They are food, drink, etc categories and cannot be changed). I want to allow the user to put their favorites on the home page. The Apple moreNavigationController editing system only allows 20 tab bar items to be rearranged due to space constraints on the editing page. This is not enough so i need to implement my own Editing screen. I set the rightBarButtonItem to nil and created my own. Using NSLog, i can see the "click" happens when clicking the EDIT button, but I cannot push using pushViewController. Nothing happens. I think it has something to do with the navigationController I am addressing...but i am not sure. ps: This all happens in my App Delegate which DOES act as both UITabBarControllerDelegate & UINavigationControllerDelegate.
I tried to do the following:
- ( void )navigationController:( UINavigationController * )navigationController_local willShowViewController:( UIViewController * )viewController_local animated:( BOOL )animated
{
UIViewController * currentController = navigationController_local.visibleViewController;
UIViewController * nextController = viewController_local;
// Do whatever here.
NSLog(#"Nav contoller willShowViewController fired\n'%#'\n'%#'\nThere are currently: %d views on the stack\n",currentController,nextController,[self.navigationController.viewControllers count]);
if ( [nextController isKindOfClass:NSClassFromString(#"UIMoreListController")])
{
UINavigationBar *morenavbar = navigationController_local.navigationBar;
UINavigationItem *morenavitem = morenavbar.topItem;
morenavitem.rightBarButtonItem = nil;
NSLog(#"Is a UIMoreListController\n");
UIBarButtonItem *editTabBarButton = [[UIBarButtonItem alloc]
initWithTitle:#"Edit"
style:UIBarButtonItemStylePlain
target:self
action:#selector(editTabBar:)];
morenavitem.rightBarButtonItem = editTabBarButton;
[editTabBarButton release];
}
}
This works to place an EDIT button at the top right of the screen -- mimicking Apple's look and feel... but when that button is clicked, you cannot exit the darn moreNavigationController.
I have tried many things. UIAlerts work, etc...but pushing (or popping -- even popping to root view) a view controller on the stack does not.
- (void) editTabBar:(id)sender {
NSLog(#"clicked edit tabbar\n");
NSLog(#"Total count of controllers: %d\n",[self.navigationController.viewControllers count]);
TabBarViewController *tabBarViewController2 = [[TabBarViewController alloc] initWithNibName:#"TabBarView" bundle:nil];
tabBarViewController2.navigationItem.title=#"Edit Tab Bar";
[self.navigationController pushViewController:tabBarViewController2 animated:YES];
[tabBarViewController2 release];
NSLog(#"finished edit tabbar\n");
}
If you click the edit button on the moreNavigationController's display page, you get the log entries like expected AND (this is strange) the views on the stack climbs -- but no page change occurs. I marked it down to not using the correct navigation controller...but I am lost on how to find which one TO use.
this is a weird one too. In the edit function if i just do this:
- (void) editTabBar:(id)sender {
self.tabBarController.selectedIndex = 0;
}
It DOES take me home (to tabbarcontroller 0)
BUT doing this:
- (void) editTabBar:(id)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}
does not work.
Does the moreNavigationController have some special quality that screws with the rest of the system?
I would try reimplementing the whole "More" functionality from scratch. In other words, store the four home tabs in your user defaults and add a dummy fifth tab that switches to your own complete reimplementation of the more view controller stack.
You could even write a lightweight subclass of UITabBarController that handled this for you.
UITabBarController is evil, so I wouldn't be at all surprised if MoreController had some special properties, too.
I have had success intercepting the More Controller in shouldSelectViewController to change the data source; you may be able to find some workaround there.
PS I am inclined to agree that you could consider redesigning your app so that you didn't need an unlimited number of viewControllers attached to the tab bar just to select categories; you might have better luck using a tool bar with a single, scrollable, custom view in it. If that's really the best way of picking categories for your app, of course.
I have one main view where I display an image, in the method viewDidLoad:
ballRect = CGRectMake(posBallX, 144, 32.0f, 32.0f);
theBall = [[UIImageView alloc] initWithFrame:ballRect];
[theBall setImage:[UIImage imageNamed:#"ball.png"]];
[self.view addSubview:theBall];
[laPalla release];
Obviously, the value of posBallX is defined and then update via a custom method call many times in the same class.
theBall.frame = CGRectMake(posBallX, 144, 32, 32);
Everything works, but when I go to another view with
[self presentModalViewController:viewTwo animated:YES];
and come back with
[self presentModalViewController:viewOne animated:YES];
the image is displayed correctly after the method viewDidLoad is called (I retrieve the values with NSUserDefaults) but no more in the second method. In the NSLog I can even see the new posBallX updating correctly, but the Image is simply no more shown...
The same happens with a Label as well, which should print the value of posBallX.
So, things are just not working if I come back to the viewOne from the viewTwo... Any idea???????
Thanks so much!
You should use dismissModalViewControllerAnimated: to switch back to viewOne from viewTwo instead of trying to present viewOne modally.
Also note that viewDidLoad is called only once - after the view controller's view is loaded into memory. If you want to perform an action once a view comes back on screen, you should do so in viewWillAppear:.
Both of these points are discussed in the UIViewController class reference and in the View Controller Programming Guide.