Back button not appearing on UINavigationController - can't debug - objective-c

The back button on a navigation controller is sometimes not appearing. Note that sometimes it does, so there is probably something else going on in som code elsewhere, but I have tried to debug this in every way I can think, and nothing seems to work.
The code for pushing the view controller is as follows (pretty standard):
CommentsTableViewController *vc = [[[CommentsTableViewController alloc] init] autorelease];
vc.puzzleID = self.puzzleModel.puzzleID;
[self.navigationController pushViewController:vc animated:YES];
To debug this problem, I have put the following code in the CommentsTableViewController in viewWillAppear and viewDidAppear (except I only register as an observer once):
self.navigationItem.hidesBackButton = NO;
[self.navigationItem addObserver:self forKeyPath:#"backBarButtonItem" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial) context:nil];
self.navigationItem.backBarButtonItem.title = #"Tactic";
NSArray *viewControllerArray = [self.navigationController viewControllers];
int parentViewControllerIndex = [viewControllerArray count] - 2;
[[viewControllerArray objectAtIndex:parentViewControllerIndex] setTitle:#"Tactic"];
None of this seems to help. Putting breakpoints in, it seems like the view controller above me in the hierarchy has a title (#"Tactic") and hidesBackButton is already NO. The backBarButtonItem property is nil and is always nil, though I think this is expected behavior even when you do have a backBarButtonItem?
EDIT: In the parent controller, I am setting hidesBackBackButton to YES at first, and then later (before I push on the next controller), setting it back to NO. When I remove these lines, the new view controller has a back button. Why would the navigation item of one view controller affect the navigation item of the next?
Any suggestions or ideas are welcome. Thanks a lot.

Perhaps you might solve the problem debugging it better.You assumed that the button that leads you back is this:
self.navigationItem.backBarButtonItem.title = #"Tactic";
But that's nil, if you want to find that button look in the navigation controller's navigation bar:
NSLog(#"%#",self.navigationController.navigationBar.topItem);
I don't see a reason why your code isn't working, and you also don't need to do this:
self.navigationItem.hidesBackButton = NO;
Try this instead:
self.navigationController.navigationBar.topItem.hidesBackButton = NO;
Anyway this works for me even if I don't set it to NO.
If this doesn't solve the problem it should help at least debugging it, and if you still have that problem post in the comments, and say what does that NSLog() print.

Ok. I've worked it out. I have no idea why this makes a difference, but it does.
In the same run loop where I was calling hidesBackButton, I was also calling:
[self.view addSubview:self.chessBoardViewController.view];
This seemed to be the line that was screwing up the navigationBar somehow. If I remove this line, it works perfectly. So the solution I found was replacing this line with:
[self.view performSelector:#selector(addSubview:) withObject:self.chessBoardViewController.view afterDelay:0];
I dont' know why this worked, so if anyone has any insights on what might be happening, please comment.

Related

Troubles with UISearchBar \ UISearchDisplayViewController

I'm having a hard time with my SearchDisplayViewController on iOS 7.
I have a searchBar hidden over a UITableViewController, like
self.tableView.tableHeaderView = searchBar;
Problem is that when I tap on the searchBar to type in something, then the view starts greying out, and I quickly tap the screen in a random point to dismiss it, coming back to the tableView, the searchBar disappears. Totally. Only on iOS 7 though.
Debugging it, the frame is always the same: 0,0,320,44. But the bar is invisible!
Also tried to do
self.tableView.contentOffset = CGPointMake(0,self.searchDisplayController.searchBar.frame.size.height);
still disappears when I do it quickly.
On iOS 6 it works just fine. Problem is only with iOS 7 as far as I'm seeing.
I don't know what it depends on, has anyone encountered the same problem I have?
As of Double tap UISearchBar with search delegate on iOS 7 causes UISearchBar to disappear, I found the workaround to actually work and solved the bug - for now.
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
[self.tableView insertSubview:self.searchDisplayController.searchBar aboveSubview:self.tableView];
}
}
I encountered the same issue, and noticed that searchDisplayControllerDidEndSearch was being called twice. The first time, the superview of self.searchDisplayController.searchBar is the UITableView, and the second time it's still a UIView.
With the accepted answer, I worry about unintended consequences or unneeded overhead from re-inserting the subview every time the search bar is double-tapped, and I also worry about it breaking with future iOS versions. Fortunately, we can take advantage of the superview strangeness like this:
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller {
if (self.tableView != self.searchDisplayController.searchBar.superview) {
[self.tableView insertSubview:self.searchDisplayController.searchBar aboveSubview:self.tableView];
}
}
If I had to guess what was happening, the UISearchBar is automatically creating a temporary UIView as its superview when it's active – this is the view seen when the search is being performed. While the UISearchBar is being dismissed, the superview gets set back to be the UITableView it had before, unless it gets dismissed so quickly that it was never properly initialized, in which case it cleans up improperly and the UITableView never gets the UISearchBar back as its child.
This solution still isn't ideal, and I think Apple must be doing something different in its own apps because their search bar UX feels a bit better. I think it would be better not to handle the second tap in the first place until the UISearchBar was ready. I tried using the other UISearchBarDelegate methods to do this, but I couldn't find an appropriate hook to override the current behavior.
I had the same problem with iOS 7 and I solved it from the apple documentation. The error most people do is that they associate the UISearchBar variable to the self.searchDisplayController.searchBar as the same...! NO NO..! They are 2 different things!!! UISearchBar should be declared and initialized and then wrapped into self.searchDisplayController as searchBar then later wrapped into self.tableView.tableHeaderView by so doing it will not disappear!!!
self.searchBar = [[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)];
self.searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchDisplayController.delegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.searchResultsDelegate = self;
[self.searchBar setPlaceholder:#"search the hell in me"];
self.tableView.tableHeaderView = self.searchDisplayController.searchBar;
More refined approach for #lehrblogger solution:
- (void)addSearchDisplayControllerBackToTableView {
if ([self.searchDisplayController.searchBar isDescendantOfView:self.tableView] == NO) {
NSLog(#"Search bar is not in current table view, will add it back");
[self.tableView insertSubview:self.searchDisplayController.searchBar aboveSubview:self.tableView];
[self.searchDisplayController setActive:NO animated:YES];
}
}
Reason for this approach: While searching the search bar is moved to search container and the superview of search bar is always some other view other than current table view.
Note: This will dismiss the search, because user tapped more than once on search bar.

icarousel not displaying items

I've been working with iCarousel for about a week now, and I've had great success with outside testing. Now, I'm trying to put it into my app and it won't display the views. I was using UIViews to be displayed originally, which was working fine in my test programs, but due to sheer frustration im going as basic as possible and have literally just copied everythinng over from the examples. I connected the delegate and datasource, I called reloadData, ive done everything i could possibly find to fix this and it's not getting fixed. here's some code implementing the actual icarousel:
- (IBAction)coverflowPressed:(id)sender {
self.carousel = [[iCarouselExampleViewController alloc]
initWithNibName:#"iCarouselExampleViewController" bundle:nil];
[self presentViewController:self.carousel animated:YES completion:nil];
}
The rest of the code is basically copied from an example that works outside my app. As i mentioned, i DID connect the delegate and dataSource. It displays the background just fine, but it's like the carousel is empty; it has no items in it, and yes, there ARE items in it. any ideas for me?
EDIT
Maybe i connected the delegate and datasource wrong. could somebody maybe explain how to do that from an app thats already halfway through production?
Breakpoints prove that it's never reaching carousel-specific functions, like viewForItemAtIndex or even awakeFromNib. viewDidLoad is called, so i set the delegate and datasource in there. Originally they were set in the nib but i changed it to programmatically. anyways heres my viewdidload method:
- (void)viewDidLoad {
[super viewDidLoad];
self.carousel.delegate = self;
self.carousel.dataSource = self;
//configure carousel
_carousel.type = iCarouselTypeCoverFlow2;
}
it reaches the end of this function but it never goes any farther with it...

Popover not being dismissed when calling dismissPopoverAnimated or clicking once outside of popover

I hope someone can help me with this weird bug. I've got a popover with buttons to perform various actions. There is a toolbar item that must be clicked to bring up the popover. Here is the action method that is called:
-(IBAction)showActions:(id)sender
{
ActionsPopUpController* controller = [[ActionsPopUpController alloc] initWithDelegate:self state:DELETE_ENABLED | FACEBOOK_ENABLED | TWITTER_ENABLED | EMAIL_ENABLED];
_actionsPopUp = [[UIPopoverController alloc] initWithContentViewController:controller];
[controller release];
[_actionsPopUp presentPopoverFromRect:_actionButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
_actionsPopUp.delegate = self;
}
As you can see, I have a property/ivar (actionsPopUp) that retains a reference to the UIPopoverController. This is used later to call dismissPopoverAnimated when I want to dismiss the popover. Here is an example of it's use:
-(void)shareWishToEmail:(id)sender
{
[_actionsPopUp dismissPopoverAnimated:YES];
[[WishCloudService sharedInstance] showMailer:self withItems:[NSArray arrayWithObject:self.item] delegate:self modal:YES];
}
In this method, I dismiss the popover first, and then perform the action associated with the button that was pressed in the popover. Unfortunately, this doesn't appear to work. The action gets performed, but the popover is not dismissed. In addition, it doesn't seem to get dismissed when the user clicks once outside of the popover. But if clicked outside again, it does get dismissed. Another observation is that the first click seems to hide/dismiss the drop shadow of the popover, but not the popover itself. It's the second click that dismisses the popover. However, no amount of calling dismissPopoverAnimated seems to dismiss the popover at all.
I've swapped in UIPopoverControllers that seem to work in other parts of the application, but get the same results, which leads me to believe that it is something specific to the UIView/UIViewController that I'm presenting the popover in. I am creating the view programmatically rather than through a NIB. It escapes me at the moment why I decided to do that, but I don't believe that it should be relevant. Someone please let me know otherwise. Here is my loadView method:
-(void)loadView
{
self.view = [self createView:_item];
self.currentView = self.view;
_wishItemViews = [[NSMutableDictionary dictionary] retain];
[_wishItemViews setObject:_currentView forKey:[NSNumber numberWithInteger:_currentIndex]];
}
I have a currentView property because I need to be able to slide new views in and out, and I'm using CATransition animations to do it. The currentView property is used to swap the views when it performs the transitions. Again, not sure if this is relevant, but I'm including it for completeness and just in case it does make a difference. Hopefully, that's enough information for someone to help point me in the right direction. Or at least prompt some additional questions that might help me think this through. Any help would be greatly appreciated.
Another observation is that the first click seems to hide/dismiss the drop shadow of the popover, but not the popover itself.
It seems you have stumbled upon the rare double-popover. ;-)

Issues with UINavigationController

I am using UINavigationController in my app. While going "Back" I want to skip one view. What I am currently doing is this :
In the viewDidAppear of the view I don't want to see I check to see if it appeared from a back button click, if so I call :
[self.navigationController popViewControllerAnimated:YES];
But what happens is this:
the unwanted view and the previous view get morphed into one view (one on top of the other).
more explanation:
the unwanted view is the 2nd view and I want to go to the rootview:
Another code that I used was:
[self.navigationController popToRootViewControllerAnimation:YES]
The problem with this approach is 2:
a) I still get a back button in the navigation bar that I should not be getting
b) The toolbar items that should be there are not there. (the toolbar itself is there, though!)
Can anyone kindly let me know what I did wrong here ? Thanks.
You can try this:
int count = [self.navigationController.viewControllers count];
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:count-2]]
Keep in mind the count is an array starting at 0 so just do count - x, taking that into consideration.
Also I am pretty sure this would work but it doesn't look clean:
UINavigationController *navController = self.navigationController;
[navController popViewControllerAnimated:NO];
[navController popViewControllerAnimated:YES];
Hope that helps.
What I needed to do in order to sovle this problem was this ::
Customize the backbutton function from the 3rd view and in the action handler popToRootViewController
Thanks.

Stop UIPopover from dismissing automatically part II

Sorry I previously posted a question here, but The answers I got didn't work (probably my fault).
Basically, I want to stop a UIPopover from dismissing automatically. I got to this piece of code:
- (BOOL) popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
return NO;
}
which I put in, but it doesn't seem to have any effect. Is there anything else I should add?
am I putting it in the right place (I was putting it in the vc.m of the view that has the popover within it)?
Thanks Very Much,
Luke
Check to make sure the UIPopover delegate is set. You can do this in code by setting the popover instance variable:
aPopover.delegate = self;