Setting editable on a NSTextField doesn't have any effect - macos

I have an NSTextField in a view that is bound to a value in the view's view controller. When a button is pressed I wish to make the text field no longer editable so I use the following code:
- (IBAction)makeTextFieldNotEditable:(id)sender {
self.textField.editable = NO;
}
Everything is bound correctly and I can confirm that the above method gets called when I press the button but the text field is still editable. How can I fix this?

This was because by default when you bind the value of an NSTextField in Interface Builder it ticks the box Conditionally Sets Editable meaning that the value the text field is bound to sets the editable property of the text field.
Unticking this box made my original code work.

Related

Make NSWindow.isMovableByWindowBackground work with NSTextField

I have a Cocoa app that shows a "quick search" window similar to Spotlight. The window contains a visual effect view and inside a NSTextField. The text field stretches across the full width of the window.
I would like to be able to move the window by dragging inside the empty area of the text field. When dragging across text in the text field, the normal editing (i.e. selection) behavior should be used instead.
In theory, moving a window by its background is easy:
window.isMovableByWindowBackground = true
However, this behavior does not work with NSTextField, because it intercepts dragging and attempts to select text instead.
Spotlight does it somehow. Here's an example:
A couple of options that I considered without success:
Tried overriding hitTest: returning nil
Tried overriding mouseDown|Up|Dragging: and forwarding to superview
Tried to use autolayout to have text field shrink to tightly wrap around its text (could not figure this one out)
For reference, I finally found a way:
Part 1: get NSTextField to grow/shrink with its content
Override intrinsicContentSize and measure its content:
private func measure(_ string:NSAttributedString) -> NSSize
{
let cell = NSTextFieldCell(textCell: stringValue)
cell.attributedStringValue = string
return cell.cellSize
}
Part 2: view setup
Add a placeholder view right after the text field
Set up auto layout to have the placeholder view to grow and shrink
Part3: all about the details
Set up the placeholder view to use the iBeam cursor to make it appear like a text field
If the user clicks in the placeholder view, make the text field the first responder
That's it.

Make NSTableView cells editable programmatically only

How to configure a view-based NSTableView to behave like so:
Rows are selectable
The user are unable to trigger edit mode by clicking a cell
Edit mode can be triggered by calling NSTableView-editColumn:row:withEvent:select: programmatically
The table view is dragged from the object library of Xcode interface builder, i.e., it uses an NSTableCellView (with an NSImageView and an NSTextField as its subviews) as the table view's cell view.
For view-based table views, -editColumn:row:withEvent:select: is relatively ineffective. It attempts to make the cell view the first responder for the window, but only certain views will accept first responder status. NSTableCellView does not, because it is not itself editable.
If you want to programmatically initiate editing in the text field within an NSTableCellView, you can do something like:
NSTableCellView* cellView = (NSTableCellView*)[tableView viewAtColumn:col row:row makeIfNecessary:YES];
if ([cellView.textField acceptsFirstResponder])
[cellView.window makeFirstResponder:cellView.textField];
To disable the user from starting editing through the UI, I think you will need to set the text field to not be editable. You would make it editable just before you initiate editing programmatically. For example, add a line cellView.textField.editable = YES; between the above two lines.
Then, you'll want to set it back to non-editable after editing ends. To do this, you can set the delegate of the text field to your controller object and implement -controlTextDidEndEditing:. Or, similarly, you can add an observer of the NSControlTextDidEndEditingNotification notification from the text field. Either way, when your code is called, you set the text field's editable property back to false. (If you don't otherwise have a reference to the text field in question, you can obtain it from the NSNotification's object property.)

Continuous NSTextField

I have a NSTextField and Label whose value is bind to same NSString in the view Controller
The problem here is the label only gets updated when I press Tab.
How do I make it continuous, so that what ever I type in the text box gets reflected in the label immediately?
As of now I am using -(void)controlTextDidChange:(NSNotification *)obj; selector, but I am expecting a binding only solution.
Select the relevant NSTextField in Interface Builder, then navigate to the Bindings Inspector. You need to make sure Continuously Updates Value is checked:

Specify editing NSTextField inside NSPopover on appearance

I'm working on an app that presents an NSPopover containing a number of NSTextFields. While I can tab between these fields as I expect, the popover is selecting a particular text field to be in the editing state when it appears, and it's not the field I want to edit; I'd like to be able to define which text field is editing on popover appearance programmatically (or in Interface Builder). How can I do this?
I've set up the appropriate key view loop by connecting IB outlets for all the various text fields involved, and I've hooked up the popover's nextResponder property to the text field I want to edit first, but that doesn't seem to have an effect - the popover will still select its preferred text field instead of mine. The Window Programming Guide suggests that I set the initialFirstResponder outlet of the window to the view I want selected, but an NSPopover is not an NSWindow and has no initialFirstResponder property (unless I'm missing something obvious).
Is there any way to specify which NSTextField I want to be editing when an NSPopover appears?
I think you said you tried using -makeFirstResponder: and passing the text field. This will set the window's firstResponder, but that's not the same as initialFirstResponder and the window must have initialFirstResponder set to something other than nil in order to respect the key view loop. (Source) A slight tweak to what you tried worked for me:
- (void)popoverWillShow:(NSNotification *)notification
{
// Set the window's initialFirstResponder so that the key view loop isn't auto-recalculated.
[[myField window] setInitialFirstResponder:myField];
}
I think you can make this work by setting all the text field's that you don't want to have focus to "selectable" instead of "Editable" in IB, this should leave the one text field you want to start with as the first responder. Then, in your popoverDidShow: method, set them all back to editable, and you should be able to tab between them as usual.

How to make UIPickerView that appears if i click on the UITextField?

How can i make a UIPickerView that appears when i select a TextField, and the input of this comes into TextField if i select a value of UIPickerView?
How to do this? Have you an example of this?
Create the UIPickerView and set it as the inputView of your text field. It will then be animated on screen for you when you start editing the text field. The picker view delegate methods can be used to update the text field's value.
You will also want to create a toolbar with a done button and set this as the inputAccessoryView - this will allow you to dismiss the picker when you have selected your value. Again, this will appear automatically above the picker view when the text field begins editing.
Please take a look at this example http://www.techotopia.com/index.php/An_iOS_4_iPhone_UIPickerView_Example
You can initially hide the picker by
picker.hidden=YES; in your viewdidload method and for showing it when touch on the textfield you can write picker.hidden=NO; inside uitextfielddidstartediting method. Thanks.

Resources