Displaying an action sheet over a disabled tab bar in tab bar partially enables it - objective-c

I think I found a bug in UIKit, but first I want to be sure I'm not insane.
I have a tab bar with a disabled tabBarItem in it. If I present an action sheet from the tab bar, then cancel/press any button in it, after the action sheet dismisses the tab bar item appears enabled, but cannot be clicked.
I want it to stay disabled.
I uploaded an example project here. Run it in the simulator and press the action sheet button on the first view controller. Note the state of the second tab bar item before and after the sheet appears. The project itself is a standard "Tabbed Application" template with one tab item disabled and an IBAction for the button added.
Is this a bug, or am I misusing the APIs?

Looks like a bug it is...
As a quick and safe workaround add this to the view controller (assuming it will be an UIActionSheet's delegate)
- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
for (UITabBarItem *item in self.tabBarController.tabBar.items) {
item.enabled = !item.enabled;
item.enabled = !item.enabled;
}
}

I have checked your Project and found a way to make it work. But I don't know actually is it a bug or not. I just find out, it is happening only when you show the actionsheet from the method using showFromTabbar: method.
[sheet showFromTabBar:self.tabBarController.tabBar];
When i changed it to show in this view only, then its not changing the tabBarItem image.
[sheet showInView:self.view];
Hope this could help you to continue to work on that project.

Related

Modal NSWindow Notification after becoming visible again

I am on objectiveC, OSX, not iOS. XCode 8.3
I have a preferences Window (custom NSWindow) that opens as a modal on my main window.
The preferences window itself contains a view with tabs. The tab height changes the windows size whenever one is clicked.
First Tab clicked:
Second Tab clicked:
Now if someone hides the application in the dock and activates it again, the preferences window becomes active with the height of tab 1, even if tab 2 is still active. So the content gets cut off.
What i need is some kind of notification that gets triggered on becoming active/visible again to trigger a resize of the window before it gets displayed.
I tried it with these notifications in my NSWindow subclass (with NSWindow delegate set).
- (void)windowDidResignMain:(NSNotification*)notification{
NSLog(#"windowDidResignMain");
}
- (void)windowDidResignKey:(NSNotification*)notification{
NSLog(#"windowDidResignKey");
}
- (BOOL)canBecomeKeyWindow{
return YES;
}
- (BOOL)canBecomeMainWindow{
return YES;
}
But none of them worked. Is it because it's a modal window?
Any help appreciated.
I found it. My mistake - my tabViewController triggered a resize on viewWillAppear with always the first tab. I changed that to the current selected tab and that was it.

On clicking a tab need to answer an alert before moving into the tab clicked - iPad programming

There are many tabs in my screen,I want to give an alert box which says "Do you want to save the changes?" if user changes anything in the page, without clicking on the save button provided in the page,he is clicking on diff tab.
I'm able to get the alert view but the tab click moves the screen to the tab which was clicked. The screen should not change until the alert view is answered.
Can anyone let me know how to suppress the screen change until the alert view is answered ?
This doesn't directly answer your question, but: what you're trying to do sounds like bad UI design. (In general, if it feels like you are fighting against UIKit, you're probably doing it the wrong.)
In this case: if you really want to ensure that a user taps a Save button before moving to a different screen, you should present that screen in a modal view, so that it is impossible to navigate to any other part of the app.
In other words, if you want to prevent a user from navigating away from a screen, don't show them buttons or tabs that would allow them to navigate away. Otherwise, you're just making more work for yourself and frustrating a user.
Implement UITabBarControllerDelegate in your app delegate's applicationDidFinishLaunching
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
self.tabBarController.delegate = self;
[window addSubview:self.tabBarController.view];
}
Then use the below delegate method,
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController;
This method is called before the tab switch and you can return no here to disable that and show an alert message instead. Once the user has performed the save either he can press on tab again or you can programmatically switch to the new tab as,
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:0];
Add this inside your delegate,
How about this for switching to the tab programmatically,
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if () {
//some code
} else {
//some other code
self.tabBarController.selectedViewController = viewController;
}
}

I cannot hide a textfield and label in my iOS app

here is the low down:
-(IBAction)button1click:(id)sender;
{
label1.hidden=YES;
textfield1.hidden=YES;
label2.hidden=NO;
textfield2.hidden=NO;
-(IBAction)button2click:(id)sender;
{
label1.hidden=NO;
textfield1.hidden=NO;
label2.hidden=YES;
textfield2.hidden=YES;
the is issue is that when i first open my screen all 4 labels are visible. By default button1 radio is checked but label2 and textfield 2 are visible when they shouldnt be. if i press button1 even though it is already selected the items with hide and then all is good. My issue is having them hidden when the screen first opens up.
Thanx all for you help
You can, in your viewDidLoad method:
-(void) viewDidLoad
{
[super viewDidLoad];
[self button1click:nil]; //nil or the instance of button1 if you need it
}
In this way, you will execute the same code when you press button1 without duplicate your code.
You can take one of two approaches to hide the label.
a) in Interface builder you can click the check box for hidden in the attributes inspector. If you do that the default behavior will always be hidden when the app launches then you can make it visible in code like your example shows
b) add your existing code to hide the label to your view controllers - (void)viewDidLoad method.
both methods work equally well.
When you create that objects you can set foo.isHidden = YES

Is there a way to select a segue anchor programmatically?

Suppose I have a Storyboard containing a view that contains a button. When the user presses this button, a popover comes up.
Thus, I need to set an anchor by dragging the segue to the button using Xcode (and then do performSegueWithIdentifier:).
So, my question is: is there a way to set this "anchor" programmatically?
Thank you.
In my case I've added programmatically several UIBarButtonItem.
The problem of only using an invisible view as an archor is that, if like in my case, the size of the UIBarButtonItem is changing it's size, the arrow of the popover doesnt appear centered, and althought it works, looks a bit strange.
How to solve it.
Create a small view in storyboard ( the size doesnt really matter ), make it invisible, and link it.
In my case this is called invisibleViewAsArchor
Connect the UIBarbutton item with the follow action.
-(IBAction) showMyPopover:(id)sender {
if([self.popoverController isPopoverVisible])
{
[self.popoverController dismissPopoverAnimated:YES];
}else{
self.invisibleViewAsArchor.frame = CGRectMake([sender view].frame.origin.x,
[sender view].frame.origin.y-50,
[sender view].frame.size.width,
[sender view].frame.size.height);
[self performSegueWithIdentifier:#"segue_to_something" sender:self];
}
}
as you can see before it shows the popover (with performSegueWithIdentifier), I'm changing the frame
of the Archor with the values from the button that has fired the event.
Hope it helps.
In the storyboard anchor the popover to some arbitrary button. Don't worry too much about which one as it will get overridden in the code.
In the view controller method prepareForSegue, add the code:
let dest = segue.destinationViewController
dest.popoverPresentationController?.barButtonItem = <your bar button here>
or if you want to anchor to a view instead
dest.popoverPresentationController?.barButtonItem = nil
dest.popoverPresentationController?.sourceView = <your view here>
You can't programmatically create segue's as explained here: Creating a segue programmatically, however, you can configure which destination controller you want to display at run-time. This is explained in the apple documentation here: Configuring the Destination Controller When a Segue is Triggered.
Hopefully this helps!
I had the same problem where I was creating a BarButtonItem programmatically. You may also be able to get around it by creating an invisible, disabled button which you can set as the anchor in IB.

Show NSStatusItem menu only if App is active

I'm using this method to show the NSStatusItem menu only if application is Active.
-(void)menuWillOpen:(NSMenu*)menu{
if(![NSApp isActive]){
[menu cancelTracking];
}
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
[window makeKeyAndOrderFront:self];
}
It perfectly works, but cancelTracking seems to block the blue highlight of the NSStatusItem. So when i click on status menu item it doesn't show the submenu and it presents the main window, but the icon is not highlighted.
Is there a way to make it happen ?
I suggest creating a custom view if you need more precise control over when the status item highlights itself. Then you can use mouseDown: etc. This is a good example of putting your custom view in a status item.