Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Data is not being transferred from iphone to iWatch (AppleWatch) on real devices

I have an iOS app and I programmed a extension for it on appleWatch. I'm sending data (NSDictionary) to the appleWatch extension using transferUserInfo method. Everything works in the simulator but when I'm trying to run the application on real devices, it seems that the iWatch is not receiving anything though the iPhone is sending the data (I found this cause I debugged the sender side).

I have configured the WCSession on both sides. I have conformed the WCSessionDelegate in the class where I'm supposed to receive the data. I'm using session:didReceiveUserInfo: method to receive the data in ExtensionDelegate but still like I said everything works fine in the simulator but nothing is being transferred on real devices.

Does anyone has a clue to what the problem is?

here's the code: in the sender side:

inside my class MensaViewController.m

- (void)viewDidLoad
   if ([WCSession isSupported]) {
        session = [WCSession defaultSession];
        session.delegate = self;
        [session activateSession];
   }
   NSLog(@"A dish is being sent");
  [session transferUserInfo:dishDictionary];
}

dishDictionary is declared inside viewDidLoad method and it contains data.

on the receiver side (Watch Extension) I configure the WCSession and receive data in ExtensionDelegate.m like this:

- (void)applicationDidBecomeActive {
    if ([WCSession isSupported]) {
        session = [WCSession defaultSession];
        session.delegate = self;
        [session activateSession];
        NSLog(@"Session activated in iWatch");
    }
}

and I have this method to receive the data:

- (void)session:session didReceiveUserInfo:(NSDictionary<NSString *,id> *)userInfo{

    NSLog(@"Received data from the iPhone");

    NSArray<NSString*> *dictionaryKeys = userInfo.allKeys;
    for(int i = 0; i < dictionaryKeys.count; i++){
        Boolean equalsMensaString = [dictionaryKeys[i] isEqualToString:@"beilagen"];
        if(equalsMensaString)
            [self handleTransferredDish:userInfo];

        Boolean equalsNewsString = [dictionaryKeys[i] isEqualToString:@"article"];
        if(equalsNewsString)
            [self handleTransferredNews:userInfo];

        Boolean equalsEventString = [dictionaryKeys[i] isEqualToString:@"description"];
        if(equalsEventString)
            [self handleTransferredEvents:userInfo];

    }
}
like image 285
Rudy.kh Avatar asked Oct 18 '22 16:10

Rudy.kh


1 Answers

If you take a look at sources function description, you can see the description of the method you are using for transferring data:

public func transferUserInfo(userInfo: [String : AnyObject]) -> WCSessionUserInfoTransfer

The system will enqueue the user info dictionary and transfer it to the counterpart app at an opportune time. The transfer of user info will continue after the sending app has exited. The counterpart app will receive a delegate callback on next launch if the file has successfully arrived. The userInfo dictionary can only accept the property list types.

So..There's no guarantee that the system will send this userInfo while you are actually using the App.

Use the following method instead:

public func sendMessage(message: [String : AnyObject], replyHandler: (([String : AnyObject]) -> Void)?, errorHandler: ((NSError) -> Void)?)

Clients can use this method to send messages to the counterpart app. Clients wishing to receive a reply to a particular message should pass in a replyHandler block. If the message cannot be sent or if the reply could not be received, the errorHandler block will be invoked with an error. If both a replyHandler and an errorHandler are specified, then exactly one of them will be invoked. Messages can only be sent while the sending app is running. If the sending app exits before the message is dispatched the send will fail. If the counterpart app is not running the counterpart app will be launched upon receiving the message (iOS counterpart app only). The message dictionary can only accept the property list types.

and for receiving:

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void)

Notice That: This send can fail if the counterpart app is not open or the Session is not paired and active. So, in the case you can not miss any data you should use updateApplicationContext or transferUserInfo (I actually prefer updateApplicationContext)

session.sendMessage(messageData, replyHandler: { (replyData) -> Void in
            replyHandler?(replyData)
            }, errorHandler: { (error) -> Void in
                print("error: code:\(error.code) - \(error.localizedDescription)")
                errorHandler?(error)
                 do {
                        try session.updateApplicationContext(messageData)
                    } catch {
                        print("There was an error trying to update watchkit app on the background")
                    }
        })

And make sure you receive this cases with proper implementation of

func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject])

like image 153
Hugo Alonso Avatar answered Oct 30 '22 17:10

Hugo Alonso