Use to, this type of syntax was needed in the "Did End On Exit" action of a UITextField:
[self.myTextField resignFirstResponder];
At least in the simulator of Xcocde 5, that code seems to be no longer needed. The keyboard will hide when you press the return button and there is no associated action attached. Is that correct or is this simulator only behavior?
I guess this code is still needed for iOS6?
Actually, the premise of your question is wrong. Nothing has changed, except that you've discovered the truth. It was never necessary to say resignFirstResponder if a text field targeted its "did end on exit" action: the mere fact of the targeting caused (and still causes) the Return key to perform dismissal automatically.
In fact, the "did end on exit" action doesn't actually have to do anything; no corresponding method need be implemented. And the target need not be a real object; it can be nil. In other words, this code will endow any text field with the "magical" property that it automatically dismisses the keyboard when the Return key is pressed:
[textField addTarget:nil action:#selector(dummy:)
forControlEvents:UIControlEventEditingDidEndOnExit];
That works (and has worked since as early as I've been using iOS, i.e. iOS 3) even though the target is nil and the action method is never implemented anywhere (there is no dummy: method in the app). It always surprises me that this important technique is not more widely known.
You still need it. To close a keyboard I make an action called "close keyboard" and connect that to my text field or text view. Here is the code...
-(IBAction)closeKeyboard {
[textfield1 resignFirstResponder];
}
Related
I have a Cocoa application that captures keypresses through a custom view in the view hierarchy. This view implements the keyUp and keyDown methods, and the keypresses are received. Even so, Cocoa still insists on playing the system error sound/ding every time I press a key. Any solutions?
Note: Although I tried to make this view first responder, it didn't work. That may have something to do with it.
If you have unsuccessfully tried to make the view the first responder, it's most likely because NSView returns NO for acceptsFirstResponder. You can have your NSView subclass override acceptsFirstResponder to return YES:
- (BOOL)acceptsFirstResponder {
return YES;
}
That should eliminate the beeps. Alternatively, you could have the NSView subclass override NSResponder's performKeyEquivalent: method to return YES, which should also eliminate the NSBeeps:
- (BOOL)performKeyEquivalent:(NSEvent *)event {
return YES;
}
UPDATE:
Not sure what to suggest. I actually wrote a "Keyboard Cleaner Helper" app that's designed to basically do something similar to what you want. (I used it on my laptop when I wanted to clean the keyboard and didn't the hundreds of key presses to randomly rename files or result in repeated error beeps).
Sample project: http://www.markdouma.com/developer/KeyboardCleanerHelper.zip
Running that app, I can't get it to beep at all (notice calls are logged to Console).
I want to make a windowless application. The problem is that I'm using a framework that shows some alert boxes sometimes, and I'm not able to suppress them (at least not without a crash).
I've set LSBackgroundOnly to 1 (in the info.plist app file), but this doesn't seem to work. Any chance I'm missing something here (maybe some other settings that I need to set)?
I've also tried creating a category for NSWindow:
Overwritten alloc and allocWithZone: so that no window gets created. This works on some situations, but starting a modal session throws exception (because sending a nil parameter to beginModalSessionForWindow:).
Tried overwriting NSApplication's beginModalSessionForWindow: and returned nil everytime, but this leads to EXC_BADACCESS somewhere in the framework (runModalSession: and endModalSession: were also overwritten, but the crash is before any of them being called).
Any other ideas will be welcome.
In case it helps, the framework that I'm using is Twain.Framework, so if instead anyone knows a way to block all UI from twain (this includes error alerts shown when a device is not connected) it would be great if you share.
It's not clear what you're hoping for. Are you hoping for an app that doesn't normally display windows but does allow the third-party framework to show its alerts? Or are you hoping to find a way to prevent the framework from showing its alerts so your app absolutely never has any windows?
If it's the former, you're probably looking for LSUIElement. That's an app which can have some UI elements, but doesn't show in the Dock or the Command-Tab application switcher and doesn't have a menu bar.
I managed to make it 'windowless' (some windows are still shown, but at least they're not visible, and they're automatically closed). I only handled modal windows, since these where shown in my situation.
I made a category for NSWindow, so that all windows are invisible, and can't become key or main windows:
-(BOOL)canBecomeKeyWindow{
[self setOpaque:NO];
self.alphaValue = 0;
return NO;
}
-(BOOL)canBecomeMainWindow{
[self setOpaque:NO];
self.alphaValue = 0;
return NO;
}
Subclassed NSApplication:
-(NSInteger)runModalForWindow:(NSWindow *)aWindow{
return NSCancelButton;
}
-(NSModalSession)beginModalSessionForWindow:(NSWindow *)aWindow{
NSModalSession session = [super beginModalSessionForWindow:aWindow];
[aWindow performSelector:#selector(close) withObject:nil afterDelay:1];
return session;
}
However, this didn't help much. In case of runModalForWindow: everything was good, since the owner of the window received a response. In case of beginModalSessionForWindow: the application got stuck, most probably because the window's owner was waiting for a specific event (e.g. button click) which it never received.
I was just trying to dismiss a UIAlertView using the following call:
[serverConnectionClosedAlertView dismissAnimated:YES];
I did some testing and everything worked nicely. When I got back to the Xcode window I saw the warning, "UIAlertView may not respond to '-dismissAnimated'. I looked up the documentation and noticed that this method is indeed not defined on UIAlertView or even UIView. The correct call should have been
[serverConnectionClosedAlertView dismissWithClickedButtonIndex:0 animated:YES];
So, I am wondering
Why did Xcode suggest the original method name (I had pressed ESC to get the list of suggestions and just picked the method above; old Eclipse/Java habit, I guess), and
Why did the code work at all? It actually did dismiss the UIAlertView without any crashes or log entries.
It was in fact called dismissAnimated: in previous versions of the SDK. It has since either been deprecated or made a private API in favor of dismissWithClickedButtonIndex:animated:, but it'll still work if you call it.
I'm trying to bind a bare esc key press to an NSMenuItem that toggles full screen (currently just a stub function). Manually selecting the menu item sends the desired IBAction. When I set the NSMenuItem's Key Equiv. in Interface Builder to an arbitrary bare key (eg. w) that key command sends the desired IBAction. When I set the Key Equiv. to command + esc, that key command sends the desired IBAction. But a bare esc key press is ignored.
I'm assuming the esc key is special-cased. Other applications (eg. Bannister's various emulators) are able to achieve this, any idea how?
I'm no Objective-C veteran, so apologies if I'm misunderstanding the question. But have you tried moving up the responder chain and grabbing the keyDown event in NSWindow? Something like:
- (void)keyDown: (NSEvent *) event {
if ([event keyCode] == 53) {
NSLog(#"Esc. pressed");
}
}
Of course, this solution will require that you subclass NSWindow.
The Escape key is tightly bound to the cancelOperation class of NSResponder.
Try to subclass your NSWindow and give it this method:
- (void)cancelOperation:(id)sender {
if (![SomeController doSomeAction]) {
[super cancelOperation:sender];
}
}
Your window will then react to the Escape key and evoke doSomeAction. That would be the method your NSMenuItem would have liked to call, but it refused to do so :)
In the doSomeAction method you should return a Boolean that indicates whether the action did actually do something. If it did, good. If it did not (and returned NO), your NSWindow will pass on the Escape key event to the next responder in the chain.
I like this solution because it gives the user audio feedback about whether his key press actually did something. Because if your method didn't do anything, and no other repsonder did do anything, there will be some "beep" sound.
Note that in an NSView without an attached window, you might have to use [self nextResponder] instead of super.
Please have a look at http://developer.apple.com/mac/library/documentation/UserExperience/Conceptual/AppleHIGuidelines/XHIGUserInput/XHIGUserInput.html
“… The Esc (Escape) key basically means “let me out of here.” It has specific meanings in certain contexts. The user can press Esc in the following situations: …”
Greetings
I'm writing a mozilla plugin on the mac. I'm trying to capture events like button clicks, etc. I've done the normal thing of creating my views in inteface builder, and linking the sentActions to methods in my program. This works in stand-alone programs.
However, in my NPAPI plugin, those methods never get called. The button reacts, depresses, whatever, but it doesn't do its action.
Instead, the NPP_HandleEvent method gets called, but I never get the MouseDown or MouseUp event, only the UpdateEvt.
I set up the buttons to accept clicks via: (superview is the Mozilla view, topview is the top of my view hierarchy.)
[superView setNextResponder: topView];
[topView setNextResponder: nil];
[browserWindow makeFirstResponder: topView];
NEVER MIND: I'm an idiot. It IS calling the button sent actions. I was looking at the wrong method. That'll teach me to leave around a zoom: method when I'm actually using a doZoom: method... D'oh,.
So, the problem was that I wasn't able to get buttons to work. The buttons were supposed to (for example) zoom an image in an IKImageView. (or rather, zoom the view). It didn't appear that it was working. The screen was flashing a lot, but nothing was happening... I put a printf in my zoom method, and it was NEVER GETTING CALLED! and so I asked the question.
Later, I noticed that I wasn't TRYING to call zoom, I was calling doZoom! doZoom WAS being called. And the reason that it wasn't zooming was an unrelated problem.
The problem ended up being that I was sending setImage to my IKImageView on every event, which re-set the view to 1-1, rightside up mode. Once I took out the extra setImage call, things started to work.
In the unlikely event that anyone else every experiences this, the answer is my cunning plan for world domination:
step 1: Don't be an idiot.
step 2: ???????
step 3: Dominate the world.
(If I could master step 1, I might just be able to figure out what step 2 was B-)