Sending data from iPhone to Apple Watch and vice versa using Swift 5

Upgrade to Swift 5.1
In this tutorial, we will learn how to send data from iPhone to Apple watch and Apple watch to iPhone using Swift 5.1. As we all familiar that Apple watch apps demands are keep growing these days, keeping in mind this tutorial maybe helpful for you.
We are going to achieve below.

Now let’s start coding

-Create a new project and choose watchOS and select iOS App with WatchKit App.

-Now enter your Product Name and select Notification Scene as per your uses.

Design your Storyboard

– Open your Main.storyboard and go to ViewController nib file.
– Add a UILabel and UIButton over the View.

-Create IBOutlet of UILabel with name label
-Add IBAction function to UIButton with name tapSendDataToWatch

Move to your UIViewController Class

Open your ViewController Class and make below changes
import UIKit
import WatchConnectivity//1

class ViewController: UIViewController {
  
  var session: WCSession?//2
  @IBOutlet weak var label: UILabel!//3
  
  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    self.configureWatchKitSesstion()//4
  }
  
  func configureWatchKitSesstion() {
    
    if WCSession.isSupported() {//4.1
      session = WCSession.default//4.2
      session?.delegate = self//4.3
      session?.activate()//4.4
    }
  }
  //5
  @IBAction func tapSendDataToWatch(_ sender: Any) {
    
    if let validSession = self.session, validSession.isReachable {//5.1
      let data: [String: Any] = ["iPhone": "Data from iPhone" as Any] // Create your Dictionay as per uses
      validSession.sendMessage(data, replyHandler: nil, errorHandler: nil)
    }
  }
}

// WCSession delegate functions
extension ViewController: WCSessionDelegate {
  
  func sessionDidBecomeInactive(_ session: WCSession) {
  }
  
  func sessionDidDeactivate(_ session: WCSession) {
  }
  
  func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
  }
  
  func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
    print("received message: \(message)")
    DispatchQueue.main.async { //6
      if let value = message["watch"] as? String {
        self.label.text = value
      }
    }
  }
}

1. Import WatchConnectivity framework, this will help to connect the iPhone and watch
2. WCSession will help us to communicate between iOS and WatckKit
3. This is IBOutlet of UILabel
4. Calling configureWatchKitSesstion to initialize WCSession
4.1 Check that WCSession is supported or not
4.2 Initializing WCSession
4.3 Set WCSessionDelegate to session
4.4 Activate WCSession in order to transfer data
5. This is IBAction function on UIButton
5.1 First check if Apple watch is reachable then send the data to Apple watch using sendMessage function of WCSession
6 Receiving data when Apple watch send to iPhone

Move to Watch and Open Watch Interface.storyboard

– Open Interface.storyboard and select InterfaceController nib file.
– Add a WKInterfaceLabel and WKInterfaceButton over the InterfaceController nib file.
– Create IBOutlet of WKInterfaceLabel and add IBAction on WKInterfaceButton with name tapSendToiPhone

Move to InterfaceController Class

Open InterfaceController Class and make below changes.
import WatchKit
import WatchKit
import Foundation
import WatchConnectivity //**1

class InterfaceController: WKInterfaceController {
  
  @IBOutlet weak var label: WKInterfaceLabel!//**2
  let session = WCSession.default//**3
  
  override func awake(withContext context: Any?) {
    super.awake(withContext: context)
    
    // Configure interface objects here.
    session.delegate = self//**4
    session.activate()//**5
  }
  
  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()
  }
  
  @IBAction func tapSendToiPhone() {//**6
    let data: [String: Any] = ["watch": "data from watch" as Any] //Create your dictionary as per uses
    session.sendMessage(data, replyHandler: nil, errorHandler: nil) //**6.1
  }
}

extension InterfaceController: WCSessionDelegate {
  
  func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
  }
  
  func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
    
    print("received data: \(message)")
    if let value = message["iPhone"] as? String {//**7.1
      self.label.setText(value)
    }
  }
}

1. Import WatchConnectivity framework
2. Crate IBoutlet of WKInterfaceLabel which we have added over nib file above
3. Get a default object of WCSession
4. Assign WCSessionDelegate to the session object
5. Activate WCSession in order to transfer data between iOS and WatchKit
6. This is IBAction function which we have added on WKInterfaceButton
6.1 Send data to iPhone using sendMessage function of WCSession
7. When the iPhone send data to then watch then didReceiveMessage delegate function will invoke.
7.1 Get the message which is sent from iPhone and set this to WKInterfaceLabel
Now run your code
Note: If you forget to activate your session then, you will get an error log “swift wcsession counterpart app not installed” message while sharing data

Read our next Article: Easiest way to dismiss keyboard UITextView

16 comments on “Sending data from iPhone to Apple Watch and vice versa using Swift 5

  1. sirgliofrei

    Greetings! Very helpful advice on this article! It is the little changes that make the biggest changes. Thanks a lot for sharing!

    Reply
  2. elena

    Hi, I setup the exact code and UI in XCODE 10.2 for iOS 13.3 simulator and watchOS 6.1. I checked every line exactly in this page and checked the compatibilty with swift 4.0 4.2 and 5.0. there is no warning, and no error; but no message send and received between simulators. I really don’t know what the problem is?

    Reply
      1. Sergey

        Same thing( did it twice – first time it was no response from phone and watch (without any error), second time it is error: WatchKit Extension[21282:1294188] [WC] WCSession iOS app not installed

        Reply
          1. swiftdevcenter_admin Post author

            Hi Stefan,
            The issue is reloved, please take a look at the updated post.

  3. Olivier

    Hi,
    Thanks for the tutorial. I have copied the whole code. My question is about how to run it. Which target to use, iPhone or Watch ? Which scheme to use ? I have defined one with an iPhone 7 + a watch S4 44. Either I get “app counterpart not installed” and I see only the iPhone screen. Either I get the two screens but the apps ignore each other. Any help ? I have restarted Xcode about 10 times already…
    Thanks

    Reply
  4. Mike D.

    Hello Author. I created this exactly and nothing is happening! Xcode 11.4 swift 5.0 Simulator: iOS 13.4 watchOS 6.2
    thank you

    Reply
    1. Mike D.

      Hello All, I found problem and fix.
      “Check your WatchKit Extention target.
      – Uncheck “Supports Running Without iOS App Installation”

      I did and sends data back and forth now. Thank you.

      Question1: I’d like to send from watch a Struct. How do we do that? thank you.

      Question 2: On phone when received data I like it to automatically do something, like create an EKEvent? Receive code has to go in App Delegate? thank you, we can discuss in email if better. Regards, Mike

      Reply
  5. Arslan Khalid

    Hello there… I am using same scenario for sharing data but issue is I want to share data even when my iPhone app is killed from background. please can you help me for this?

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *