Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing Data between interface controllers in WatchKit

How would I pass data stored in a label from my Interface Controller to another interface controller in WatchKit using Swift? I can't seem to find an answer anywhere, hope someone here can help me. I've included the section of my code that deals with calculating the value I need passed. I basically want to show the same value that was calculated by the user and elaborate more on it in the next Interface Controller named ResultsController. Any help is greatly appreciated :D

class InterfaceController: WKInterfaceController {
     var currentValue: String = "0"

     func setDisplayValue(value: Double)
    {
        var percent = value
        //  check if value is an integer
        if value % 1 == 0
        {
            // our value is an integer
            currentValue = "\(Int(value))"// new value %
        }
        else
        {
            // our value is a float
            currentValue = "\(value)"
        }
        // Display 2 decimal places in final amount
       var round =  NSString(format:"%.2f", value)
        displayLabel.setText("$\(round)") // Display final value
        // This value is what I want to be passed to another label in another IC.
    }

    // Answer Tapped
    @IBAction func totalTapped() {
        if command != nil
        {
            let answer = command!.executeWithNewValue((currentValue as NSString).doubleValue)
            setDisplayValue(answer)
            command = nil
            calculationExecuted = true
        }
    }
}

This is the second Interface controller that I want the value from the first one to be displayed in using a label.

import WatchKit
import Foundation


class ResultsController: WKInterfaceController {

    @IBOutlet weak var totalLabel: WKInterfaceLabel!

    override func awakeWithContext(context: AnyObject?) {
        super.awakeWithContext(context)

        // Label to hold the same value as in previous Interface Controller
        totalLabel.setText("")
    }

    override func willActivate() {
        // This method is called when watch view controller is about to be visible to user
        super.willActivate()
    }

    override func didDeactivate() {
        // This method is called when watch view controller is no longer visible
        super.didDeactivate()
    }

}

Edit: Here is the tutorial I followed, I manipulated it a bit to be essentially a tip cal. I added in ResultsController to hold the information inputted by the user using the calculator from InterfaceController but I can't seem to pass the data over to my labels in RC, in the Command I removed subtract and divide since I wouldn't be needing those. So the only calculation buttons I have are multiply and addition. Example of how it should work: Enter in an amount 12.58 tap multiply and enter in 15 tap add and it displays the final amount of 14.46 I need to pass over all of those values to RC in separate labels.

Github Tutorial - Apple Watch

Here is what I am trying to accomplish: Passing the initial amount to a label, and the tip amount, as well as the final cost to separate labels to resemble a bill.

like image 271
adrlan Avatar asked Apr 02 '15 01:04

adrlan


3 Answers

for swift 5, use pushController

A scene -> B scene

1.set your scene name . (look at the red circle) enter image description here

  1. from controller to be like the below. put the scene name(red circle) that you want to move to as first argument. and second argument is your data that you want to send to the next controller

    AinterfaceController.swift
    (@IBAction) func changeScene(){
       self.pushController(withName: "next scene identifier: the name that u set in the red circle", context: yourData)
    
    } 
  1. "To" controller to be like the below.
    BinterfaceController.swift
    ...
        override func awake(withContext context: Any?) {
            super.awake(withContext: context)
            print("what you send from A controller", context)
            
        }
like image 189
Energy Avatar answered Nov 01 '22 23:11

Energy


The best way to do this is to override the contextForSegueWithIdentifier method that is called when you segue from one view to the next.

The method of passing data between WKInterfaceControllers is a bit different than the method for doing so with UIViewControllers in a traditional iOS app.

Normally, you'd do something like this:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "showDetail" {
        let controller: DetailViewController = (segue.destinationViewController as UINavigationController).topViewController as DetailViewController
        controller.myVariable = myValue
    }
}

However, there is no prepareForSegue method in WatchKit. The contextForSegueWithIdentifier WKInterfaceController method is similar, but it has a glaring difference: it doesn't provide you with an instance of the destination view controller.

Instead, you return data from the method, and access that data within your target class.

So, in your case, it would look like this:

// In InterfaceController
override func contextForSegueWithIdentifier(segueIdentifier: String) -> AnyObject? {
    // You may want to set the context's identifier in Interface Builder and check it here to make sure you're returning data at the proper times

    // Return data to be accessed in ResultsController
    return self.currentValue
}

// In ResultsController
override func awakeWithContext(context: AnyObject?) {
    super.awakeWithContext(context)

    // Make sure data was passed properly and update the label accordingly
    if let val: String = context as? String {
        self.totalLabel.setText(val)
    } else {
        self.totalLabel.setText("")
    }
}
like image 19
AstroCB Avatar answered Nov 02 '22 00:11

AstroCB


Use pushControllerWithName:context: or presentControllerWithName:context:

NSDictionary *exampleObj = @{@"key":@"value"};
[self pushControllerWithName:@"YourInterfaceControllerName" context:exampleObj];

On the receiving end, use awakeWithContext:context

- (void)awakeWithContext:(id)context
{
    [super awakeWithContext:context];
    NSString *value = context[@"key"];
}

As context is an (id), you can pass anything, not just NSDictionary.

like image 15
bhautikmewada191 Avatar answered Nov 02 '22 00:11

bhautikmewada191