The blue focus ring outside NSTextField missing? - xcode

In normal case, a blue retangle would appear outside a NSTextField object which becomes the first responder, like this image:
link for Normal Case
However, I got a NSTextField that have no the blue border outside. Why is that?
Here is how it happerns:
1> I create a typical MAC OS app.
2> I switch app's subview by calling the corresponding view's addSubview: and removeFromSuperview methods.
3> In one subview (which is actually the image referenced above) I click the "Next" button. Its action is something like this (defined in the subview's controller .m file):
- (IBAction)actionNextClicked:(id)sender{
//_hdlThreadNext is a NSThread object
[[_hdlThreadNext alloc] initWithTarget:self selector#selector(threadNext:) object:nil];
[_hdlThreadNext start];
}
And the thread is like:
- (void)threadNext:(id)sender{
#autoreleasepool{
BOOL success;
[CATransation begin];
/* send username and password and decrypt responce */
... // balabala... and set "success"
if (success){
[[self view] removeFromSuperview];
[self sendMessageToSuperview:#"Add Next View"]; // Superview's method, telling superview to call addSubview: to add another subview
}
else{
/* Nothing special to do */
}
[CATransation commit];
}
}
4> The subview switch to another one. Its combo view seemed to be OK: image for combo view
But the other NSTextView's blue border would NOT appear anymore!
Does Any guy know what wrong I had done? Thank you very much!

Perhaps I did totally wrong programming, so that few people met this problem.
I found a way to solve this problem. I mentioned that all (or most of?) the graphic changes should be done in main thread in a blog. Therefore I change the "if(success)" as:
if(success){
dispatch_async(dispatch_get_main_queue()' ^{
[[self view] removeFromSuperview];
[self sendMessageToSuperview:#"Add Next View"];
});
}
Solved, the focus rings come back.

Related

how do i reference the window associated with a nswindowcontroller

I have a subclassof NSWindowController with an associated xib file.
From my app delegate I display this using the following code:
if(!wc)
wc = [[NSWindowController alloc]initWithWindowNibName:#"MyNewWindowController"];
[wc showWindow:nil];
This displays the window. Now I want to reference that window in the new window controller but can't work out how. Specifically I have a button on the new window and I want to write something like:
- (IBAction)doStuffAndCloseWindow:(id)sender
{
[self doSomeStuff];
[*window* orderOut:nil];
}
I've tried creating a window variable (like the one created in appdelegate) but the compiler says my window variable is private.
So have do I declare and reference a window in my MyNewWindowController.m?
Thanks
That would be the 'window' method of NSWindowController. It's also a property that you can access via ".window".
So, in the first code snippet, that would be:
[wc window]
and in the second code snippet (assuming "doStuffAndCloseWindow" is part of your subclassed NSWindowController):
- (IBAction)doStuffAndCloseWindow:(id)sender
{
[self doSomeStuff];
[[self window] orderOut:nil];
}
Thanks to Michael, see above, first declare your subclassed NSwindowController thus
#property IBOutlet MyNewWindowController *wc;
Then in the implementation of the subclassed window controller, you can refer to the associated window with
[[self window] .....];
For example
[[self window] orderOut:self];

UINavigationBar jumps 20pixels during transitionFromViewController

In trying to attempt to use Apple's UIViewController containment I have encountered a problem with animating the transition between two UIViewControllers.
Here is the set up... I have created a UITabBarController and within one of the tabs I have created a UIViewController as a container. This ViewController manages the transition between a UIViewController and a UINavigationController. The before view is:
When the Next button is tapped the view begins it's transition with a flipFromRight transition. During the transition, the Navigation bar is in "to" view but is located 20pixels down from the top edge of the view. Picture below:
The green is the background color of the container view. Once the new view completes the transition, the Navigation bar snaps up to the top of the view and the final result is:
The time to snap in place is independent of the duration of the animation. I achieve the final state that I want, but the transition is a problem.
I have instrumented the viewController lifecycle and the frames of the Navigation bar and the UITableView are as specified in the XIB. The xib looks like this:
Here is the code:
In -viewDidLoad -
_fromVC = [[FromVC alloc] initWithNibName:#"FromVC" bundle:nil delegate:self];
[self addChildViewController:_fromVC];
[self.view addSubview:_fromVC.view];
[_fromVC didMoveToParentViewController:self];
In my button handler -
- (void)buttonSelected
{
//
// Create the "to" View controller
//
ToVC *toVC = [[ToVC alloc] initWithNibName:#"ToVC" bundle:nil];
//
// Create the navigation controller for the study activity
//
_toNavCon = [[UINavigationController alloc] initWithRootViewController:toVC];
[self addChildViewController:_toNavCon];
[_fromVC willMoveToParentViewController:nil];
[self transitionFromViewController:_fromVC
toViewController:_toNavCon
duration:0.7
options:UIViewAnimationOptionTransitionFlipFromRight
animations:nil
completion:^(BOOL finished) {
[_fromVC removeFromParentViewController];
[_toNavCon didMoveToParentViewController:self];
}];
}
There is no code in "to" view controller that changes the appearance of the view controller.
Another bit of information... When I "toggle In-Call status bar" in the simulator the gap at the top of the navigation bar is the height of the In-Call status bar.
I have looked at everything on the web and there is nothing that helps. Has anyone seen this and has anyone fixed it?
I did find an answer!! Subclass UINavigationController and override
- (BOOL)wantsFullScreenLayout{
return NO;
}
Apparently, UINavigationController and UITabController always want the full screen (default YES) - adjusting for the status bar - and you can not set this property any other way. It has been working for me.

scrollRectToVisible UITextField doesn't scroll with Autolayout

[self.scrollView scrollRectToVisible:textField.bounds animated:YES];
I can't seem to get my UIScrollView to scroll at all so that it doesn't obscure my UITextField. I thought that scrollRectToVisible would be my savior but it looks like a no go. Maybe I'm missing something like translating the coordinates of my textField to my scrollView. Either way check out my sample project.
https://github.com/stevemoser/Programming-iOS-Book-Examples/tree/master/ch20p573scrollViewAutoLayout2
Oh, and this project might be missing the delegate connection but I checked that and it still doesn't scroll.
I've seen other questions similar to this but none that mention Autolayout.
I was having issues with scrollRectToVisible:: as well after converting to Auto Layout. I just changed it to a direct call to setContentOffset:: and it started working again.
I had the same problem, I wanted to scroll an autolayouted UITextEdit into view without making it the first responder.
For me the issue was that the bounds of the UITextField were set later on during the auto layout pass, so if you do it immediately after setting up the layout the bounds are not valid yet.
To workaround I did create a descendant of UITextField, did overwrite setBounds: and added a 0 timer to scroll into view "later on" (You can't scroll in that moment because the auto layout pass of the system might no be finished at that point)
#interface MyTextField: UITextField
{
bool _scrollIntoView;
}
..
#end
#implementation MyTextField
-(void)setBounds:(CGRect)bounds
{
bool empty=CGRectIsEmpty(self.bounds);
bool isFirstResponder=self.isFirstResponder;
[super setBounds:bounds];
if (empty && !isFirstResponder && _scrollIntoView)
[self performSelector:#selector(scrollIntoViewLater) withObject:nil afterDelay:0];
else if (empty && isFirstResponder)
[self performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0];
}
-(void)scrollIntoViewLater
{
CGRect r=[scrollView convertRect:self.bounds fromView:self];
[scrollView scrollRectToVisible:r animated:TRUE];
}
#end
If the field should be additionally editable with the on screen keyboard, simply call becomeFirstResponder later on: it scrolls automagically into view above the keyboard using the private scrollTextFieldToVisible API which in turn calls scrollRectToVisible:animated: of the scrollview.
Your sample link is broken btw...

UITableView becomes unresponsive

UITableViewCell becomes unresponsive this was a very different problem with a very different solution.
My tableView which is a subView in a UIViewController initially works fine and I can select individual rows in the table. However, I have created my own popup when a row is selected (the popup is a UIView) that appears towards the bottom of the screen. As this pops-up I also create a another UIView which covers the screen behind the popup and it makes the background go dim. The third thing that happens is that i create a UITapGestureRecogniser to keep track of the user's taps, and if they tap outside the UIView then the two UIViews and the TapGestureRecogniser are removed and call the deselectRowAtIndex... method.
However, it is at this point that I cannot use the tableView, as i want to be able to select a different string within the tableView and the popup to appear again (the popup will eventually contain links that will enable the user to move to different viewControllers).
I have tried to reload the data, remove the tableview and replace it, edit the didSelectRowAtIndex, remove the deselectRowAtIndex method, however nothing I tried seems to work and i can't find anything on stackoverflow as my question seems to be quite specific (although I apologise if there is something out there).
I'll add a few parts of my code in, however, I'm not sure where the problem is and I may not have copied the right part in.
The remove overhead is the selector method from the tapGesture
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(_popOverView == nil)
{
_popOverView = [[UIView alloc]initWithFrame:CGRectMake(20, 200, 280, 150)];
_popOverView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"wood.jpeg"]];
}
if(_mask == nil)
{
_mask = [[UIView alloc] initWithFrame:self.view.frame];
[_mask setBackgroundColor:[UIColor colorWithWhite:0.0 alpha:0.78]];
}
if (_tapDetector == nil)
{
_tapDetector= [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(removeOverHead:)];
}
[self.view addSubview:_mask];
[self.view addSubview:_popOverView];
[self.view addGestureRecognizer:_tapDetector];
}
-(void) removeOverHead:(UITapGestureRecognizer*) sender
{
CGPoint locationOfTap = [_tapDetector locationInView:self.view];
if (locationOfTap.y < (200 + 150) && locationOfTap.y > 200 && locationOfTap.x > 20 && locationOfTap.x < (20 + 280) ) {
NSLog(#"%f,%f",[_tapDetector locationInView:self.view].x,[_tapDetector locationInView:self.view].y);
}
else
{
[_mask removeFromSuperview];
[_popOverView removeFromSuperview];
[_tapDetector removeTarget:self action:#selector(removeOverHead:)];
/*this idea doesn't work :(
[self.tableView removeFromSuperview];
[self.view addSubview:_tableView];*/
}
}
I really hope the answer is in here and is very simple, and thank you in advance for taking the time to read this.
Solved it! Sorry for wasting your time. It was the wrong remove method for the gestureRecogniser. I replaced
[_tapDetector removeTarget:self action:#selector(removeOverHead:)]
with
[self.view removeGestureRecognizer:_tapDetector]
as the UIGestureRecogniser was lingering and obstructing the tableView!!
If you stick a breakpoint or NSLog() inside the else block of that remove method, do you get inside it?
It sounds like your if statement might be off. You should use CGRectContainsPoint(). However if I understand correctly, you're attempting to dismiss everything when the user taps the dimming background view. You could make this view a button or you could compare the touch's view pointer to the pointer to the background view.

How to add the Navigation Bar's view to a PopOver's PassThroughViews?

I have a PopoverController view that allows a user to download a file. On button press, the popOver view will expand in size, display download status, and the main view controller will be obscured by an unhidden "cover" view that has been added to the PopoverController's "passThroughViews" property so that the user can not accidentally dismiss the pop over while the file is downloading.
My problem is that, in storyboards, my main viewController is embedded in a Navigation Controller. I can't seem to cover the navigation controller's bar with a view in the storyboard, and if the user presses anywhere on the navigation bar then the popover will disappear and the user will lose the download's progress bar.
How do I either cover up the navigation bar with my "cover" view, or how do I add the navigation bar's view to my popOverController's passThroughViews?
Opening the Popover from the main viewController:
- (IBAction)openDataOptionsPopOver:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
PopOverViewController *optionsWindow = [storyboard instantiateViewControllerWithIdentifier:#"dataOptions"];
self.popUp = [[UIPopoverController alloc] initWithContentViewController:optionsWindow];
[self.popUp setDelegate:self];
[nextNavButton setEnabled:NO]; //Disabling barButtonItem on the navigationController
optionsWindow.containerPopOver = self.popUp; //Pointer to the popover, to resize it later.
optionsWindow.coverView = self.coverView; //Pointer to the coverView, to (un)hide later
[popUp presentPopoverFromRect:[sender frame] inView:[sender superview] permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
Setting the passThroughViews property inside of the PopoverViewController:
//Expands the popOver on press of "refreshFileButton" to display progressView
-(void) explodeWindow
{
//setting self.navigationController.view and ...visibleViewController.view here didn't seem to work ...
[containerPopOver setPassthroughViews:[NSArray arrayWithObjects:coverView, nil]];
[containerPopOver setPopoverContentSize:CGSizeMake(600, 400) animated:YES];
[titleBarItem setTitle:#"Downloading File. Please Wait ..."];
[refreshFileButton setHidden:YES];
[progressView setHidden:NO];
[downloadLabel setHidden:NO];
[coverView setHidden:NO];
[progressView setProgress:0.0 animated:NO];
}
I've tried adding self.navigationController.view to passThroughViews with no success--it actually turns out to be a null pointer. And I can't seem to place a UIView at any level in storyboards that will cover all my controls without obscuring the popOver. What am I missing here? And thanks for reading.
Edit:
As Aglaia points out below out, implementing the following, and avoiding passThroughViews, is probably the best way to do this.
- (BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
//Don't dismiss our popover when the view covering our controls is present
if([coverView isHidden]){
return YES;
}else{
return NO;
}
}
Maybe there is something I am missing, but why don′t you just implement a new view controller with its navigation bar set to none and present it modally on button press? Then when the download is finished you just dismiss the view controller.
If you want the user to see the underlying view you can use a UIAlertView instead.
Alternatively set you view controller as the delegate of the popover controller and forbid the user to dismiss your popover on touch outside through
- (BOOL) popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController
{
return NO;
}
Then when you want to dismiss it call dismissPopoverAnimated:
to cover the whole screen including navigation bar:
[myView setFrame:[[UIScreen mainScreen] bounds];
[self.navigationController.view addSubview:myView];

Resources