How can I do this in Swift?
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
if (sender.state == UIGestureRecognizerStateEnded) {
NSLog(#"UIGestureRecognizerStateEnded");
//Do Whatever You want on End of Gesture
}
else if (sender.state == UIGestureRecognizerStateBegan){
NSLog(#"UIGestureRecognizerStateBegan.");
//Do Whatever You want on Began of Gesture
}
}
I don't know how to transform that sender declaration in Swift. Thanks!
It's essentially the same code -- a function that checks the value of the parameter's state property:
func handleLongPress(gestureRecognizer: UILongPressGestureRecognizer) {
switch gestureRecognizer.state {
case .Began:
println("UIGestureRecognizerState.Began")
case .Ended:
println("UIGestureRecognizerState.Ended")
default:
break;
}
}
func handleLongPress (sender: UILongPressGestureRecognizer){
if sender.state == UIGestureRecognizerStateEnded {
println(UIGestureRecognizerStateEnded)
}else if (sender.state == UIGestureRecognizerStateBegan){
println(UIGestureRecognizerStateBegan)
}
}
try this. I just translated what you have written in obj-c
Related
It seems that all of the examples for GameplayKit are always in Swift. I've decided not to move over to swift for now and I've just been translating a lot of code into Objective C, which is fine most of the time.
I'm trying to implement the isValidNextState method from the GKState class, but I'm getting an error for the switch statement and I'm not sure what it wants...it seems in Swift this is fine, but not in obj C. The error that I'm getting is:
Error: Statement requires expression of integer type('__unsafe_unretained Class _Nonnull' invalid
What should I have in the switch statement instead of stateclass?
-(BOOL) isValidNextState:(Class)stateClass {
switch (stateClass) { //ERROR ON THIS LINE
case [InvulnerableState class]: //not sure what this should be either
return YES;
break;
default:
break;
}
return NO;
}
Here's the equivalent in Swift which works fine:
override func isValidNextState(stateClass: AnyClass) -> Bool {
switch stateClass {
case is InvulnerableState.Type:
return true
default:
return false
}
}
Your isValidNextState method should be:
- (BOOL)isValidNextState:(Class)stateClass {
return stateClass == [InvulnerableState class];
}
And if you have multiple next valid states, it should be, for example:
- (BOOL)isValidNextState:(Class)stateClass {
return stateClass == [InvulnerableState class] ||
stateClass == [InvulnerableState2 class];
}
I am trying to re-write an app in swift which is currently in Objective-C. How would I change this single line into Swift, as my current attempt does not prove correct
Tabata *tabata = [notification object];
Here is the entire function:
- (void)stateChanged:(NSNotification*)notification
{
if (enabled)
{
Tabata *tabata = [notification object];
switch (tabata.getState) {
case EXERCISE:
case RELAXATION:
[player play];
break;
default:
break;
}
}
}
And here is what I've converted into Swift:
func stateChanged(notifcation: NSNotification) {
if enabled {
var tabata: Tabata! = notification.object //error "Use of unresolved identifier 'notification'"
switch tabata.getState() {
case .EXERCISE: fallthrough
case .RELAXATION:
player.play()
break
default:
break
}
}
}
In Swift you have to downcast objects of type AnyObject rather then declare the type
var tabata = notification.object as! Tabata
func stateChanged(notification: NSNotification) {
if(enabled) {
var tabata: Tabata = notification.object as! Tabata
switch tabata.getState() {
case .EXERCISE:
fallthrough
case .RELAXATION:
player.play()
break
default:
break
}
}
}
Hope this helps!
I'm a beginner in SpriteKit programming, and have been trying to figure out how to handle input from the keyboard.
What I've found so far is that you should subclass NSResponder and implement it like this:
#interface AppDelegate : NSResponder <NSApplicationDelegate>
-(void)keyUp:(NSEvent *)theEvent;
-(void)keyDown:(NSEvent *)theEvent;
#end
#implementation AppDelegate
-(void)keyUp:(NSEvent *)theEvent
{
NSLog(#"Key Released");
}
-(void)keyDown:(NSEvent *)theEvent
{
NSLog(#"Key Pressed");
}
#end
Obviously, there are a few more methods/properties in the interface and implementation of AppDelegate but I didn't put them there to keep the question relevant.
Next, I would start using key codes to detect which keys are being pressed, but the keyUp and keyDown methods don't even get called. I'm not sure why.
Any Help?
Update:
Thanks for your answers! I discovered that you have to implement keyUp and keyDown directly in your scene class, because they won't get called from the AppDelegate. Thanks again for the help!
The easiest way I know is to implement the keyDown method in your SKScene (and not directly in the AppDelegate). You don't have to subclass anything.
- (void)keyDown:(NSEvent *)event {
[self handleKeyEvent:event keyDown:YES];
}
- (void)keyUp:(NSEvent *)event {
[self handleKeyEvent:event keyDown:NO];
}
Then use the method handleKeyEvent:(NSEvent *)event keyDown:(BOOL)downOrUp to check which key has been pressed :
- (void)handleKeyEvent:(NSEvent *)event keyDown:(BOOL)downOrUp {
// First check the arrow keys since they are on the numeric keypad.
if ([event modifierFlags] & NSNumericPadKeyMask) { // arrow keys have this mask
NSString *theArrow = [event charactersIgnoringModifiers];
unichar keyChar = 0;
if ([theArrow length] == 1) {
keyChar = [theArrow characterAtIndex:0];
switch (keyChar) {
case NSUpArrowFunctionKey:
self.defaultPlayer.moveForward = downOrUp;
break;
case NSLeftArrowFunctionKey:
self.defaultPlayer.moveLeft = downOrUp;
break;
case NSRightArrowFunctionKey:
self.defaultPlayer.moveRight = downOrUp;
break;
case NSDownArrowFunctionKey:
self.defaultPlayer.moveBack = downOrUp;
break;
}
}
}
// Now check the rest of the keyboard
NSString *characters = [event characters];
for (int s = 0; s<[characters length]; s++) {
unichar character = [characters characterAtIndex:s];
switch (character) {
case 'w':
self.defaultPlayer.moveForward = downOrUp;
break;
case 'a':
self.defaultPlayer.moveLeft = downOrUp;
break;
case 'd':
self.defaultPlayer.moveRight = downOrUp;
break;
case 's':
self.defaultPlayer.moveBack = downOrUp;
break;
case ' ':
self.defaultPlayer.fireAction = downOrUp;
break;
}
}
}
I took this code from the Apple SpriteKit Adventure game. I found it very usefull to learn SpriteKit :)
Swift (2.0) version of HeyFara's answer. I've just popped "breaks" in where you would make your actual function calls.
public override func keyDown(theEvent: NSEvent) {
handleKeyEvent(theEvent, keyDown: true)
}
public override func keyUp(theEvent: NSEvent) {
handleKeyEvent(theEvent, keyDown: false)
}
public func handleKeyEvent(event:NSEvent, keyDown:Bool){
if event.modifierFlags.contains(NSEventModifierFlags.NumericPadKeyMask){
if let theArrow = event.charactersIgnoringModifiers, keyChar = theArrow.unicodeScalars.first?.value{
switch Int(keyChar){
case NSUpArrowFunctionKey:
break
case NSDownArrowFunctionKey:
break
case NSRightArrowFunctionKey:
break
case NSLeftArrowFunctionKey:
break
default:
break
}
}
} else {
if let characters = event.characters{
for character in characters.characters{
switch(character){
case "w":
break
default:
print(character)
}
}
}
}
}
Here is rougeExciter version of HeyFara's answer but in Swift 4.2... in case someone out there find this old post... as myself a few minutes ago :)...
public override func keyDown(with event: NSEvent) {
handleKeyEvent(event, keyDown: true)
}
public override func keyUp(with event: NSEvent) {
handleKeyEvent(event, keyDown: false)
}
public func handleKeyEvent(_ event: NSEvent, keyDown: Bool){
if event.modifierFlags.contains(NSEvent.ModifierFlags.numericPad) {
if let theArrow = event.charactersIgnoringModifiers, let keyChar = theArrow.unicodeScalars.first?.value{
switch Int(keyChar){
case NSUpArrowFunctionKey:
break
case NSDownArrowFunctionKey:
break
case NSRightArrowFunctionKey:
break
case NSLeftArrowFunctionKey:
break
default:
break
}
}
} else {
if let characters = event.characters{
for character in characters {
switch(character){
case "w":
break
default:
print(character)
}
}
}
}
}
If you want to know whenever a key is pressed, you should subscribe to the global event manager.
[NSEvent addGlobalMonitorForEventsMatchingMask:(NSKeyDownMask) handler:^(NSEvent *event) {
[NSEvent removeMonitor:event];
This will call the handler when ever a key is pressed.
I find it very hard to find anything official on this matter.
I have a TextView and override the keyDown event and try to detect if the user pressed Ctrl + Enter.
- (void)keyDown:(NSEvent *)theEvent
{
if([theEvent modifierFlags] & NSControlKeyMask && /* how to check if enter is pressed??? */)
{
NSLog(#"keyDown: ctrl+enter");
if(_delegate)
{
if([_delegate respondsToSelector:#selector(didSomething:)])
{
[_delegate performSelector:#selector(didSomething:) withObject:nil];
}
}
}else
{
[super keyDown:theEvent];
}
}
I have tried different things but nothing worked.
anyone?
(i'm sorry to ask such a trivial question but i have googled for a while now and haven't found anything)
unichar c = [theEvent charactersIgnoringModifiers] characterAtIndex:0];
if(([theEvent modifierFlags] & NSControlKeyMask) && (c == NSCarriageReturnCharacter || c == NSEnterCharacter) {
// do stuff
}
Alternatively, you can use the delegate's textView:doCommandBySelector::
- (BOOL)textView:(NSTextView *)aTextView doCommandBySelector:(SEL)aSelector {
// insertLineBreak: is the method sent when a user presses control-return in a text view
if (aSelector == #selector(insertLineBreak:)) {
// do stuff
return YES;
}
}
return NO;
}
Instead of overriding -keyDown:, you could override the keyboard action (insert a line break) that’s sent when ctrl-return is typed in a text view:
- (void)insertLineBreak:(id)sender {
NSLog(#"ctrl-return");
if(_delegate)
{
…
}
}
I want to use a wrapping text field that can potentially contain carriage returns in my app. Is there any way to force the NSTextField object to write a carriage return into the text area instead of sending its action to its target when the Return key is pressed?
This is covered in Technical Q&A QA1454, which also enumerates reasons why one would use NSTextField instead of NSTextView in this case.
You can implement the following method in the text field delegate:
- (BOOL)control:(NSControl*)control
textView:(NSTextView*)textView
doCommandBySelector:(SEL)commandSelector
{
BOOL result = NO;
if (commandSelector == #selector(insertNewline:))
{
// new line action:
// always insert a line-break character and don’t cause the receiver
// to end editing
[textView insertNewlineIgnoringFieldEditor:self];
result = YES;
}
return result;
}
Okay, I figured out one way to do it, but this very well may not be the best (or even a good) way. I subclassed NSTextField, and overrode -textShouldEndEditing: like so:
-(BOOL)textShouldEndEditing:(NSText *)textObject {
NSEvent * event = [[NSApplication sharedApplication] currentEvent];
if ([event type] == NSKeyDown && [event keyCode] == 36) {
[self setStringValue:[[self stringValue] stringByAppendingString:#"\n"]];
return NO;
}
else {
return [super textShouldEndEditing:textObject];
}
}
I found a combination of Sean and Bevarious worked best for me. Sean's answer assumes that the new line is always wanted to be added to the end (instead of for instance where the user's cursor is placed).
-(BOOL)textShouldEndEditing:(NSText *)textObject
{
NSEvent * event = [[NSApplication sharedApplication] currentEvent];
if ([event type] == NSKeyDown && [event keyCode] == 36)
{
[textObject insertNewlineIgnoringFieldEditor:nil];
return NO;
}
else
{
return [super textShouldEndEditing:textObject];
}
}
Swift version:
override func textShouldEndEditing(textObject: NSText) -> Bool {
let event = NSApplication.sharedApplication().currentEvent
if event?.type == NSEventType.KeyDown && event?.keyCode == 36 {
self.stringValue = self.stringValue.stringByAppendingString("\n")
return false
} else {
return super.textShouldEndEditing(textObject)
}
}