msk
msk

Reputation: 8905

WatchConnectivity file transfer not working

I am using WatchConnectivity to transfer an image from iOS to Watch OS. When debugging in simulator I am facing a problem

The file is transferred successfully as I can see in (sender side i.e. iOS)

public func session(session: WCSession, didFinishFileTransfer fileTransfer: WCSessionFileTransfer, error: NSError?)

Now from XCode I stop iOS simulator, change target to Watch App, Ctrl+Run Watch App (just run, no build).The below method is called.

public func session(session: WCSession, didReceiveFile file: WCSessionFile) 

At last I do

NSFileManager.defaultManager().moveItemAtURL(file.fileURL, toURL: destinationFileURL)

This call throws because there is no file at file.fileURL (which I checked in my MAC also).

The file.fileURL.path! is like this

/Users/<user name>/Library/Developer/CoreSimulator/Devices/DAD8E150-BAA7-43E0-BBDD-58FB0AA74E80/data/Containers/Data/PluginKitPlugin/2CB3D46B-DDB5-480C-ACF4-E529EFBA2657/Documents/Inbox/com.apple.watchconnectivity/979DC929-E1BA-4C24-8140-462EC0B0655C/Files/EC57EBB8-827E-487E-8F5A-A07BE80B3269/image

Any clues?

Upvotes: 2

Views: 2706

Answers (2)

BootMaker
BootMaker

Reputation: 1647

As the Apple documentation of WCSessionDelegate Protocol Reference says regarding

- (void)session:(WCSession *)session didReceiveFile:(WCSessionFile *)file

when getting back the (WCSessionFile *)file parameter:

The object containing the URL of the file and any additional information. If you want to keep the file referenced by this parameter, you must move it synchronously to a new location during your implementation of this method. If you do not move the file, the system deletes it after this method returns.

So the best to move it ASAP to a new location. It's safe as the system keeps the reference and doesn't delete it during the move.

- (void)session:(WCSession *)session didReceiveFile:(WCSessionFile *)file {

    NSError *error;
    NSFileManager *fileManager = [NSFileManager defaultManager];

    NSString *cacheDir = [[NSHomeDirectory() stringByAppendingPathComponent:@"Library"] stringByAppendingPathComponent:@"Caches"];
    NSURL *cacheDirURL = [NSURL fileURLWithPath:cacheDir];

    if ([fileManager moveItemAtURL: file.fileURL toURL:cacheDirURL error: &error]) {

       //Store reference to the new URL or do whatever you'd like to do with the file
       NSData *data = [NSData dataWithContentsOfURL:cacheDirURL];

    }

    else {

       //Handle the error
    }

}

WARNING! You have to be careful with the thread handling as delegates of WCSession run in the background queue so you have to switch to main queue if you'd like to work with UI.

Upvotes: -2

msk
msk

Reputation: 8905

I found the problem. I was dispatching some code to main thread and the file move code was also inside that. WC framework clean up the file just after this method ends so the file must be moved before this function returns. I moved that code outside performInMainThread block and everything is working like charm.

public func session(session: WCSession, didReceiveFile file: WCSessionFile) 
{
   // Move file here
   performInMainThread { () -> Void in
         // Not here   
   }
}

Upvotes: 8

Related Questions