I'm a newbie developing for iOS devices. I inserted an UITextField on InterfaceBuilder, and I assigned with the code:
#interface ComposeViewController : UIViewController {
id <ComposeViewControllerDelegate> delegate;
IBOutlet UITextField *notificationTitle;
}
How I could allow to close the keyboard when the user press the "Return" key?
Set the Delegate of the UITextField to your ViewController, add a referencing outlet between the File's Owner and the UITextField, then implement this method:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if (textField == yourTextField) {
[textField resignFirstResponder];
}
return NO;
}
Inherit UITextFieldDelegate protocol
In viewDidLoad method set:
yourTextField.delegate = self
Implement the delegate method below:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[yourTextField resignFirstResponder];
return NO;
}
Inherit UITextFieldDelegate protocol and implement textFieldShouldReturn:, that's you will catch "return" event.
Inside textFieldShouldReturn write [notificationTitle resignFirstResponder];
Add a action target to the event Did End on Exit(UIControlEventEditingDidEndOnExit), in the target function remove the first responder from the text filed using resignFirstResponder.
Adding action target
Note:
1. Nib --- give action to even Did End on Exit
2. In code add target action to the event UIControlEventEditingDidEndOnExit.
Related
I have a document-based app with a tool bar containing several NSButton which I need to validate. Base on other code here, I have subclassed NSToolbar:
#interface CustomToolbar : NSToolbar
#end
#implementation CustomToolbar
-(void)validateVisibleItems
{
for (NSToolbarItem *toolbarItem in self.visibleItems)
{
NSResponder *responder = toolbarItem.view;
while ((responder = [responder nextResponder]))
{
if ([responder respondsToSelector:toolbarItem.action])
{
[responder performSelector:#selector(validateToolbarItem:) withObject:toolbarItem];
}
}
}
}
#end
MyDocument (the File's owner) is set as the delegate of the toolbar. However
-(BOOL)validateToolbarItem:(NSToolbarItem *)toolbarItem
is never called. The buttons have an action set on them, so not sure why [responder respondsToSelector:toolbarItem.action] is always false.
I have tried subclassing the NSButton items:
#interface DocumentToolbarActionItem : NSToolbarItem
#implementation DocumentToolbarActionItem
-(void)validate
{
Document* document = [[self toolbar] delegate];
[self setEnabled:[document validateUserInterfaceItem:self]];
}
#end
But this results in an endless loop.
The document's validateUserInterfaceItem: method works for all other items in the app and I need to have my toolbar button call it to determine if they should be enabled or not.
My guess is that you're not calling through [super validateVisibleItems] and, so, losing the superclass behaviour of validation through the responder chain.
I have a cell-based NSOutlineView which displays NSTextFieldCell objects.
I'd like to respond to keydown or keyup events so as to make the text contained in the NSTextFieldCell bold when the text contains certain preset keywords. What is the most elegant way to achieve this - should I:
Subclass NSOutlineView and override the keydown method
Subclass NSTextFieldCell
Utilize a delegate of some kind
Utilize some other approach
Thanks very much in advance to all for any info!
Found it.
In awakeFromNib:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(actionToTakeOnKeyPress:) name:NSControlTextDidChangeNotification object:theNSOutlineViewThatContainsTheNSTextFieldCell];
Then add a method like this:
- (void) actionToTakeOnKeyPress: (id) sender
{
//will be called whenever contents of NSTextFieldCell change
}
To intercept key presses in a way that they can still be filtered out, various NSResponder messages may be overwritten, such as keyDown: or interpretKeyEvents:.
To be able to do that, a subclass of a NSTextView needs to be used as the field editor. For that, one subclasses NSTextFieldCell and overrides fieldEditorForView:, returning the subclass (see Custom field editor for NSTextFieldCell in an NSTableView).
Here's the relevant code excerpts:
In a subclassed NSTextFieldCell (which then has to be assigned in Interface Builder for the editable column, or returned by the NSTableViewDelegate's dataCellForTableColumn message):
- (NSTextView *)fieldEditorForView:(NSView *)aControlView
{
if (!self.myFieldEditor) {
self.myFieldEditor = [[MyTextView alloc] init];
self.myFieldEditor.fieldEditor = YES;
}
return self.myFieldEditor;
}
It also requires the declaration of a property in the #interface section:
#property (strong) MyTextView *myFieldEditor;
And then in MyTextView, which is a subclass of NSTextView:
-(void)keyDown:(NSEvent *)theEvent
{
NSLog(#"MyTextView keyDown: %#", theEvent.characters);
static bool b = true;
if (b) { // this silly example only lets every other keypress through.
[super keyDown:theEvent];
}
b = !b;
}
I'm trying to get my program to recognize a double click with an NSCollectionView. I've tried following this guide: http://www.springenwerk.com/2009/12/double-click-and-nscollectionview.html but when I do it, nothing happens because the delegate in IconViewBox is null:
The h file:
#interface IconViewBox : NSBox
{
IBOutlet id delegate;
}
#end
The m file:
#implementation IconViewBox
-(void)mouseDown:(NSEvent *)theEvent {
[super mouseDown:theEvent];
// check for click count above one, which we assume means it's a double click
if([theEvent clickCount] > 1) {
NSLog(#"double click!");
if(delegate && [delegate respondsToSelector:#selector(doubleClick:)]) {
NSLog(#"Runs through here");
[delegate performSelector:#selector(doubleClick:) withObject:self];
}
}
}
The second NSLog never gets printed because delegate is null. I've connected everything in my nib files and followed the instructions. Does anyone know why or an alternate why to do this?
You can capture multiple-clicks within your collection view item by subclassing the collection item's view.
Subclass NSView and add a mouseDown: method to detect multiple-clicks
Change the NSCollectionItem's view in the nib from NSView to MyCollectionView
Implement collectionItemViewDoubleClick: in the associated NSWindowController
This works by having the NSView subclass detect the double-click and it pass up the responder chain. The first object in the responder chain to implement collectionItemViewDoubleClick: is called.
Typically, you should implement collectionItemViewDoubleClick: in the associated NSWindowController, but it can be in any object within the responder chain.
#interface MyCollectionView : NSView
/** Capture double-clicks and pass up responder chain */
-(void)mouseDown:(NSEvent *)theEvent;
#end
#implementation MyCollectionView
-(void)mouseDown:(NSEvent *)theEvent
{
[super mouseDown:theEvent];
if (theEvent.clickCount > 1)
{
[NSApplication.sharedApplication sendAction:#selector(collectionItemViewDoubleClick:) to:nil from:self];
}
}
#end
Another option is to override the NSCollectionViewItem and add an NSClickGestureRecognizer like such:
- (void)viewDidLoad
{
NSClickGestureRecognizer *doubleClickGesture =
[[NSClickGestureRecognizer alloc] initWithTarget:self
action:#selector(onDoubleClick:)];
[doubleClickGesture setNumberOfClicksRequired:2];
// this should be the default, but without setting it, single clicks were delayed until the double click timed-out
[doubleClickGesture setDelaysPrimaryMouseButtonEvents:FALSE];
[self.view addGestureRecognizer:doubleClickGesture];
}
- (void)onDoubleClick:(NSGestureRecognizer *)sender
{
// by sending the action to nil, it is passed through the first responder chain
// to the first object that implements collectionItemViewDoubleClick:
[NSApp sendAction:#selector(collectionItemViewDoubleClick:) to:nil from:self];
}
What you said notwithstanding, you need to be sure you followed step four in the tutorial:
4. Open IconViewPrototype.xib in IB and connect the View's delegate outlet with "File's Owner":
That should do ya, provided you did follow the rest of the steps.
I created a View-Based NSTableView with a single column. This column is populated with a standard NSTableCellView from Interface Builder (I chose the version with image and textfield).
Now I want to make the textfield in the column editable.
My first attempt was to modify the NSTextField from Interface builder and set its behaviour as Editable. It works, indeed when I select a row and I push the enter key the field becomes editable and I can change its value. I thought I would be able to intercept this change thanks to some NSTableViewDataSource method like tableView:setObjectValue:forTableColumn:row: but this method never gets called in response of a textfield edit action.
Which is the right way to deal with editable field in a view-based NSTableView system? I suppose that the NSTableViewDataSource has something to do with it but I don't know how to get its methods called.
Create a subclass of NSTableCellView. (The appropriate .h and .m files) Make the class respond to the NSTextFieldDelegate protocol. Implement the control:textShouldEndEditing: method. Make this subclass the delegate of your label control.
Here is some example code.
CategoryListCell.h
#interface CategoryListCell : NSTableCellView
#end
CategoryListCell.m
#interface CategoryListCell()<NSTextFieldDelegate>
#property (weak) IBOutlet NSTextField *categoryLabel;
#property (assign) BOOL editing;
#property (copy) NSString* category;
#end
#implementation CategoryListCell
- (BOOL)control:(NSControl*)control textShouldBeginEditing:(NSText *)fieldEditor {
self.editing = YES;
return YES;
}
- (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor; {
if (self.editing) {
self.editing = NO;
[self mergeFromSource:self.category toDestination:self.categoryLabel.stringValue];
}
return YES;
}
- (void)mergeFromSource:(NSString*)source toDestination:(NSString*) destination {
// your work here
}
#end
Sounds like you need to subclass the NSView that's in the NSTableView cell and make the subclassed view a delegate of the textfield. Your view will then get text change notifications via the NSTextField delegate method:
- (void)textDidChange:(NSNotification *)notification;
I'm pretty new to mac development (coming from a web and iOS background) and I can't work out how I could get a notification every time the value of an NSTextView changes. Any ideas?
Ups I just saw that you want a callback from NSTextView and not NSTextField
Just add in the header of the object which should be the delegate the protocol
#interface delegateAppDelegate : NSObject <NSApplicationDelegate, NSTextViewDelegate> {
NSWindow *window;
}
After that you add a method like
-(void)textDidChange:(NSNotification *)notification {
NSLog(#"Ok");
}
Make sure you connected the delegate property of the NSTextView (not NSScrollView) with the object which should receive the delegate
Here's the solution:
NSTextView *textView = ...;
#interface MyClass : NSObject<NSTextStorageDelegate>
#property NSTextView *textView;
#end
MyClass *myClass = [[MyClass alloc] init];
myClass.textView = textView;
textView.textStorage.delegate = myClass;
#implementation MyClass
- (void)textStorageDidProcessEditing:(NSNotification *)aNotification
{
// self.textView.string will be the current value of the NSTextView
// and this will get invoked whenever the textView's value changes,
// BOTH from user changes (like typing) or programmatic changes,
// like textView.string = #"Foo";
}
#end
set the nstextfield's delegate. in the .h file of the delegate you add the delegate protocol
In the .m file you add a method like -(void)controlTextDidChange:(NSNotification *)obj {
NSLog(#"ok");
}
I hope that helps
Set the delegate and then use
- (void) controlTextDidChange: (NSNotification *) notification
{
}