Mac OS 10.14+ NSTextField in Sheet will not programatically update after sheet is displayed - cocoa

I have an NSPanel that I display as a sheet using nswindow:beginsheet:completionhandler:.
Once it is displayed, I change an NSTextfield in the NSPanel with setStringValue.
This works in 10.12 and 10.13, but not in in 10.14+, where the NSTextField cannot change after the sheet is displayed.
Any idea why, or how to fix this in 10.14+? I can find nothing relevant in the 10.14 release notes.
Here is the relevant code:
// Declarations
NSWindow *thisWindow;
IBOutlet NSPanel *progressPanel;
IBOutlet NSTextField *progressText;
// Show the sheet
[thisWindow beginSheet:progressPanel completionHandler:^(NSModalResponse returnCode) {
}];
// Update the NSTextField
- (void) progressSetData: (NSString *) data
{
[progressText setStringValue:data];
progressText.needsDisplay = YES;
[progressPanel display];
}

Related

How on OS X to programmatically force initial adjustment the size of image in an ImageWell, as ImageWell changes size due to LayoutConstraints

NSWindow
NSImageWell - with constraint to all four side of the Window's containerView
NSImage - is put in Well via NSPageControl
Using the mouse, I resize the Window and the ImageWell expands or contracts with the Window as desire.
The image in the Well remains the same size regardless of Window size.
The image does resize correctly, based on the size change of Window, if I drag the image a bit with the mouse.
How and where do I send a message to get this size to change "automatically" ?
Do I need to monitor size changes in the Window using Notifications?
Sorry, I was not clear. I want the image in the image well to maintain its
aspect ratio and to resize itself each time the Window is resized. Currently, when the window is resized, the user sees no change in the size of the image. He can however, cause the image to resize correctly by click dragging on the image or Window content view. I want the user to see this
resizing take place immediately, without needing to use the mouse. For example of an image that has an aspect ratio of 4/3. if the window is 4" x 4" , then when the image is added, it appears as 4" by 3". If the window goes to 8" x 8", then the image should automatically go to 8" x 6".
Guilherme was good enough to send me his demo NSView app. If, like in his app, I set an image in IB, my app also successfully resizes not only the ImageView but also the Image itself.
The problem appears to be because I put the images into the ImageView via an NSPageController. The only way to get the image to resize is to do a two finger drag inside the window.contentView
After Resizing window:
New Image Appears
Then following a two-finger drag on image :
<https://www.dropbox.com/s/d2he6bdzxbeefok/Screen%20Shot%202015-09-12%20at%2013.26.50.png?dl=0>
Below is relevant code:
AppDelegate follows:
#import "AppDelegate.h"
#import "MyImageView.h"
#interface AppDelegate ()
#property (strong, nonatomic) IBOutlet NSWindow *window;
#property (strong, nonatomic) IBOutlet NSPageController *pageController;
#property (strong, nonatomic) IBOutlet MyImageView *imageView;
#property (weak) IBOutlet NSTextField *infoLabel;
#property NSArray *imageArray;
#end
#implementation AppDelegate
#pragma mark Window delegate
- (void)windowDidResize:(NSNotification *)notification{
//[_window layoutIfNeeded];
//[_imageView doSelfLayout];
}
- (void)awakeFromNib {
[_window setDelegate:self];
[_imageView setTranslatesAutoresizingMaskIntoConstraints:NO];
_imageArray = #[ [NSImage imageNamed:#"eggplant.png"],
[NSImage imageNamed:#"sandwich.png"],
[NSImage imageNamed:#"yoghurt.png"]];
[_pageController setDelegate:self];
[_pageController setArrangedObjects:_imageArray];
[_pageController setTransitionStyle:NSPageControllerTransitionStyleStackBook];
// Set info label's text
NSString *info = [NSString stringWithFormat:#"Image %ld/%ld", ([_pageController selectedIndex]+1), [_imageArray count]];
[_infoLabel setStringValue:info];
}
#pragma mark Page Controller delegate methods:
- (void)pageController:(NSPageController *)pageController didTransitionToObject:(id)object {
/* When image is changed, update info label's text */
NSString *info = [NSString stringWithFormat:#"Image %ld/%ld", ([_pageController selectedIndex]+1), [_imageArray count]];
[_infoLabel setStringValue:info];
//[_window layoutIfNeeded];
}
- (NSString *)pageController:(NSPageController *)pageController identifierForObject:(id)object {
NSString *identifier = [[NSNumber numberWithInteger:[_imageArray indexOfObject:object]] stringValue];
return identifier;
}
- (NSViewController *)pageController:(NSPageController *)pageController viewControllerForIdentifier:(NSString *)identifier {
/* Create new view controller and image view */
NSViewController *vController = [NSViewController new];
NSImageView *iView = [[NSImageView alloc] initWithFrame:[_imageView frame]];
[iView setImage:(NSImage *)[_imageArray objectAtIndex:[identifier integerValue]]];
[iView setImageFrameStyle:NSImageFrameNone];
/* Add image view to view controller and return view controller */
[vController setView:iView];
return vController;
}
#end
What option have you selected for the scaling property in IB?
Here's a sample project, the image resizes automatically with Proportionally Up or Down selected.
I have made a demo Cocoa project zipfile below that has what I was looking for, namely an OS X app that :
- uses NSPageController in History mode to display an array of images (Portrait and Landscape) in a resizeable window
- imageView maintains imagefile aspect ratio as it automatically resizes
- images list can be traversed using a PreviousButton and a NextButton, or using a touch pad, with a two-finger swipe.
https://www.dropbox.com/s/7qgmg5dr1bxosqq/PageController3%203.zip?dl=0
It is pretty basic stuff, but I post it with the hope it can same someone else some time. Mark

How do I recieve the current value of a slider in code? in cocoa

i have draged vertical slider in my ui and lable for to show the slider value when i move the slider.
i have written following ibaction method.but it is not working. could you please help me in solving the issue.
-(IBAction)sliderval:(id)sender{
NSSlider *slider=[[NSSlider alloc]init];
[slider setMinValue:50];
[slider setMaxValue:100];
[slider setTarget:self];
[slider setAction:#selector(sliderDidMove:)];
[_textField setValue:slider];
}
Drag and drop UISlider and UILabel to view in xib. connect IBOutlet to interface variables and IBAction with event 'Value Changed'.
#interface ViewController ()
{
__weak IBOutlet UISlider *slider;
__weak IBOutlet UILabel *sliderValueLbl;
}
#end
- (IBAction)sliderMoved:(id)sender {
sliderValueLbl.text = [NSString stringWithFormat:#"%f",slider.value];
}

How to make a NSTextField added to a NSView Draggable

Let me elaborate the steps i am doing
Create Mac 10.9 Project
Drag a CustomView (Let's call it myView) to the .xib
Drag a NSButton to the .xib but out side the CustomView
Now programatically (using a other class) i add a NSTextField to the CustomView when the button is clicked by this code
NSTextField *textField = [[NSTextField alloc] init];
[textField setBezeled:NO];
[textField setEditable:NO];
[textField setSelectable:NO];
[textField setFont:[NSFont fontWithName:#"Arial" size:20]];
[textField setStringValue:#"Hello World!"];
int textWidth = textField.fittingSize.width;
int textHeight = textField.fittingSize.height;
[textField setFrame:NSMakeRect(0, 0, textWidth, textHeight)];
[myView addSubview:textField];
Now i see that the TestField is added to myView
All i want is the user can drag the textField movable inside myView
i added the following code
- (void)mouseDown:(NSEvent *)event{
NSLog(#"Hi");
}
But the NSLog is not getting shown
How do i make the NSTextField draggable?
Note: Because mouse-moved events occur so frequently that they can
quickly flood the event-dispatch machinery, an NSWindow object by
default does not receive them from the global NSApplication object.
However, you can specifically request these events by sending the
NSWindow object an setAcceptsMouseMovedEvents: message with an
argument of YES.
From Apple Docset

NSPopover transiency when popover is in status bar

I'm making an app which lives in status bar. When status item is clicked, NSPopover pops up.
It looks like this:
Here's the problem: I want it to be "transient", that is if I click anywhere outside of the popover, it will close. And while NSPopoverBehaviorTransient works fine when popover is in a window, it doesn't work when it's in status bar.
How can I implement such behavior myself?
It turned out to be easy:
- (IBAction)openPopover:(id)sender
{
// (open popover)
if(popoverTransiencyMonitor == nil)
{
popoverTransiencyMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask handler:^(NSEvent* event)
{
[self closePopover:sender];
}];
}
}
- (IBAction)closePopover:(id)sender
{
if(popoverTransiencyMonitor)
{
[NSEvent removeMonitor:popoverTransiencyMonitor];
popoverTransiencyMonitor = nil;
}
// (close popover)
}
What wasn't easy, though, is that there are nasty issues with having a popover pop out of NSStatusItem (it didn't behave as desired when Mission Control was invoked or space switched to a full-screen window). I had to implement a custom window that always floats above the NSStatusItem and deals with switching to a full-screen window etc. It seemed easy, but clearly status items weren't designed for something like that ;)
The approach that I use is similar to the above answer except I have everything combined into one method instead of using two separate IBActions.
First, I declare the following properties
#property (strong, nonatomic) NSStatusItem *statusItem;
#property (strong, nonatomic) NSEvent *popoverTransiencyMonitor;
#property (weak, nonatomic) IBOutlet NSPopover *popover;
#property (weak, nonatomic) IBOutlet NSView *popoverView;
then in awakeFromNib I set up the status bar item
- (void)awakeFromNib {
self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
self.statusItem.title = #"Title";
self.statusItem.highlightMode = YES;
self.statusItem.action = #selector(itemClicked:);
}
followed by the method that is called when the status bar item is clicked
- (void)itemClicked:(id)sender {
[[self popover] showRelativeToRect:[sender bounds] ofView:sender preferredEdge:NSMinYEdge];
if (self.popoverTransiencyMonitor == nil) {
self.popoverTransiencyMonitor = [NSEvent addGlobalMonitorForEventsMatchingMask:(NSLeftMouseDownMask | NSRightMouseDownMask | NSKeyUpMask) handler:^(NSEvent* event) {
[NSEvent removeMonitor:self.popoverTransiencyMonitor];
self.popoverTransiencyMonitor = nil;
[self.popover close];
}];
}
}
which makes the popover appear and also close when the user clicks outside the view.
Note that in Interface Builder you must set the behavior of the popover to Transient so the popover will close when the user clicks the status item.

Xcode/iOS5: Show UIDatePicker when UITextField is pressed (+ hide default keyboard)

I'd like to call UIDatePicker only when UITextField is active. When the date is picked, it should be shown in the same UITextField.
I even don't know how to call the Picker.
Can anyone help me?
there is a delegate method called
-(void)textFieldDidBeginEditing:(UITextField*)textField
{
[textField resignFirstResponder];
in this you have to do this
pick = [[UIDatePicker alloc] init];
[pick setFrame:CGRectMake(0,200,320,120)];
[pick addTarget:self action:#selector(done) forControlEvents:UIControlEventValueChanged]
[self.view addSubview:pick];
}
in
-(void)done
{
[textfield setText:pick.date];
}
release the pick in dealloc
To add to Hitman's answer, I think you should implement the
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
instead and return NO. Then show the date picker and fill the UITextField text according to the picker selection.

Resources