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!
Related
I do not know how to convert the following Objective-C code into swift. How should I do ?
Objective-c
if (operations) {
if ([operations isKindOfClass:[NSArray class]]) {
for (id <MyOperation> operation in operations) {
if (operation) {
[operation cancel];
}
}
} else if ([operations conformsToProtocol:#protocol(MyOperation)]){
[(id<MyOperation>) operations cancel];
}
[operationDictionary removeObjectForKey:key];
}
swift
if operations != nil {
// doto .......
}
Try this code:
if operations != nil {
// doto .......
if (operations?.isKindOfClass(NSArray) != nil){
for operation in operations as! [MyOperation]{
operation.cancle()
}
} else if operations?.conformsToProtocol(MyOperation){
(operations as MyOperation).cancle()
}
operationDictionary.removeObjectForKey(key)
}
I didn't test it so may be you have to make little bit changes into this code.
Hope this will help.
I usually don't help people with complete conversions, but...
if let operations: AnyObject = operations {
if operations is NSArray {
for operation in operations as! [MyOperation] {
operation.cancel()
}
}
else if let operation = operations as? MyOperation {
operation.cancel()
}
operationDictionary.removeObjectForKey(key)
}
Can someone tell me if I have translated the first 2 lines correctly to Swift and if the first part is correctly? Also, could anyone help me figure out the rest. I can't figure out how to translate the if statement at the bottom..
[C addTarget:self action:#selector(outsideOfKey: forEvent:) forControlEvents:UIControlEventTouchDragOutside|UIControlEventTouchDragInside];
[C addTarget:self action:#selector(keyGetsLeft: forEvent:) forControlEvents:UIControlEventTouchUpOutside | UIControlEventTouchUpInside];
-(void) outsideOfKey:(id)sender forEvent:(UIEvent *)event
{
for(UITouch *t in [event allTouches])
{
CGPoint touchPoint = [t locationInView:window];
if(CGRectContainsPoint(C.frame, touchPoint))
{
C.highlighted = YES;
}
else{
C.highlighted = NO;
}
Translated to swift
C.addTarget(self, action:Selector("outsideOfKey:forEvent:"), forControlEvents:.TouchDragOutside)
C.addTarget(self, action:Selector("outsideOfKey:forEvent:"), forControlEvents:.TouchDragInside)
C.addTarget(self, action:Selector("keyGetsLeft:forEvent:"), forControlEvents:.TouchUpOutside)
C.addTarget(self, action:Selector("keyGetsLeft:forEvent:"), forControlEvents:.TouchUpInside)
func outsideOfKey (sender: AnyObject, forEvent: UIEvent) {
let touch = event.allTouches() as? UITouch
for touch
{
var touchPoint : CGPoint = touch.locationInView(window)
if(CGRectContainsPoint(C.frame, touchPoint))
{
C.highlighted = YES;
}
else{
C.highlighted = NO;
}
}
Try something like:
C.addTarget(self, action:Selector("outsideOfKey:forEvent:"), forControlEvents:.TouchDragOutside | .TouchDragInside)
C.addTarget(self, action:Selector("keyGetsLeft:forEvent:"), forControlEvents:.TouchUpOutside | .TouchUpInside)
func outsideOfKey(sender: AnyObject, forEvent event: UIEvent) {
if let touches = event.allTouches()?.allObjects as? [UITouch] {
for touch in touches {
var touchPoint : CGPoint = touch.locationInView(window)
if CGRectContainsPoint(C.frame, touchPoint) == true {
C.highlighted = true;
} else {
C.highlighted = false;
}
}
}
}
Points:
You can still use the "|" operator on enums in swift (most of the time)
You don't put parentheses around the conditional clause in swift
YES and NO are not valid in swift, you much use true and false
Swift does not support sets so it is easiest to get the touches as an Array so you can iterate using a simple swift for...in loop
The "if let ..." pattern is called optional binding, if the right hand side is not nil "touches" will be set to the value and the code in the following braces will be executed, otherwise it will skip the block of code
The way "?" is used after ".allTouches()" is called optional chaining, if .allTouches() returns nil, the whole expression will return nil
Hope this is of some use to you, let me know if you have any more swift queries!
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
I'm attempting to use Tony Million's Reachability within a new Swift based app. I have it implemented in another app I wrote in Obj C, but I'm having issues with getting the proper syntax in Swift. The code blocks are as follows:
override func viewDidLoad() {
super.viewDidLoad()
messageText.text = ""
var reach: Reachability = Reachability(hostName: "www.apple.com")
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reachabilityChanged", name: kReachabilityChangedNotification, object: nil)
reach.reachableBlock = Reachability()
{
dispatch_async(dispatch_get_main_queue(), {
self.messageText.text = "Enter search criteria...";
})
}
reach.unreachableBlock = Reachability()
{
dispatch_async(dispatch_get_main_queue(), {
self.messageText.text = "Attempting to contact network...";
})
}
reach.startNotifier()
}
AND
func reachabilityChanged(note: NSNotification)
{
var reach: Reachability = Reachability()
if(reach.isReachable())
{
messageText.text = "Enter search criteria...";
}
else
{
messageText.text = "Attempting to contact network...";
}
}
My issues are first, my "blocks" for "reachable" and "unreachable" are not the correct syntax and I'm at a loss for what is the proper syntax for these blocks. My second issue is with the "reachabilityChanged" function. I get an error stating "-[_TtC9icdDRPlus20SearchViewController reachabilityChanged]: unrecognized selector sent to instance" which I'm again at a loss. Condsider my Obj C code as follows:
-(void)viewDidLoad
{
[super viewDidLoad];
NSString *popUpShownOnce = #"YES";
NSInteger swipeCount = 0;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:popUpShownOnce forKey:#"popDisplayed"];
[defaults setInteger:swipeCount forKey:#"showswipearrows"];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(reachabilityChanged:)
name:kReachabilityChangedNotification
object:nil];
[[UIApplication sharedApplication] setStatusBarHidden:NO];
Reachability * reach = [Reachability reachabilityWithHostname:#"somesite.com"];
reach.reachableBlock = ^(Reachability * reachability)
{
dispatch_async(dispatch_get_main_queue(), ^{
searchForText.placeholder = #"Enter search criteria...";
});
};
reach.unreachableBlock = ^(Reachability * reachability)
{
dispatch_async(dispatch_get_main_queue(), ^{
searchForText.placeholder = #"Attempting to contact network...";
});
};
[reach startNotifier];
}
-(void)reachabilityChanged:(NSNotification*)note
{
Reachability * reach = [note object];
if([reach isReachable])
{
searchForText.placeholder = #"Enter search criteria...";
}
else
{
searchForText.placeholder = #"Attempting to contact network...";
}
}
Assistance is greatly appreciated. The questions are as follows:
1. What is the proper translation for the reachable and unreachable blocks from Obj C to Swift?
2. If my addObserver call is correct, why might I get the unrecognized selector error? If not correct, what is the proper call?
Thanks in advance.
The correct syntax for closures is { (<params>) -> <return type> in <statements> }:
reach.reachableBlock = { (reachability) in
dispatch_async(dispatch_get_main_queue(), {
self.messageText.text = "Enter search criteria...";
})
}
With NSNotificationCenter, looks like you missed the colon in the selector argument:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reachabilityChanged:", name: kReachabilityChangedNotification, object: nil)
Your error after making the changes that #Austin recommended is that self.reachabilityRef in SCNetworkReachabilitySetCallback is NULL.
try:
func reachabilityChanged(note: NSNotification!) {
var reach: Reachability! = Reachability(reachabilityRef: note.object as SCNetworkReachability)
if(reach.isReachable()) {
messageText.text = "Enter search criteria...";
} else {
messageText.text = "Attempting to contact network...";
}
}
UPDATE:
It would seem that SCNetworkReachability is not currently fully working with Swift: according to this: https://twitter.com/marksands/status/474717606004273152
I got it to work like this:
var reachability: Reachability?
override func viewDidLoad() {
super.viewDidLoad()
// Setup reachability
reachability = Reachability(hostName: "www.google.com")
reachability!.reachableBlock = { (reach) in
dispatch_async(dispatch_get_main_queue(), {
self.titleLabel.attributedText = Utilities.myAttributedText("Online", mySize: 18, myFont: "HelveticaNeue", myColor: UIColor.whiteColor())
self.titleLabel.sizeToFit()
})
}
reachability!.unreachableBlock = { (reach) in
dispatch_async(dispatch_get_main_queue(), {
self.titleLabel.attributedText = Utilities.myAttributedText("Offline", mySize: 18, myFont: "HelveticaNeue", myColor: UIColor.whiteColor())
self.titleLabel.sizeToFit()
})
}
reachability!.startNotifier()
}
this worked for me:
//Reachability
myReachabilityInstance = Reachability(hostName: "www.google.com")
myReachabilityInstance?.reachableOnWWAN = false
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reachabilityDidChangeMethod", name: kReachabilityChangedNotification, object: nil)
myReachabilityInstance?.startNotifier()
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.