watchOS `transferFile`

The documentation states that

Warning
Always test Watch Connectivity file transfers on paired devices. The Simulator app doesn’t support the transferFile(_:metadata:) method.

but not which error (if any) will actually be thrown when trying to execute transferFile(_:metadata:) on simulator.

Could somebody share the actual error?
At the moment I'm seeing this:

2022-09-03 13:47:22.742104+0900 JDict[11441:4173123] [WC] -[WCSession notifyOfFileError:withFileTransfer:] <WCSessionFileTransfer: 0x6000039ac0a0, session file: <WCSessionFile: 0x600000fce640, identifier: DB927476-A2CC-4E30-934D-EBC80D2B8CE0, file: /Users/username/Library/Developer/CoreSimulator/Devices/AE8422DC-5FCE-4319-A2B7-E04E3743D424/data/Containers/Data/Application/C738703C-C6E6-472F-8266-3F148F5468C4/tmp/CDF111BE-CD68-4B2F-95A8-BDECB7DD8A10-11441-00000516D3127532, hasMetadata: YES>, transferring: NO> with WCErrorCodeFileAccessDenied

but can't be sure this is not because of another issue. I can't test on real device right now because I don't have a iOS16 phone and watchOS 9 watch right now.

Further, what would be a viable strategy for development on simulator?
I feel like using fixtures on the watch app with #if targetEnvironment(simulator) seems cumbersome and was wondering about a better solution.

Looking forward to hearing your thoughts!

Replies

I get errors like this:

[WC] -[WCFileStorage enumerateFileTransferResultsWithBlock:] could not load file data at path /Users/username/Library/Developer/CoreSimulator/Devices/3ED00B83-5532-4721-8590-CB5E4B22C503/data/Containers/Data/Application/2AE6F6E2-9AFD-4144-A6EB-68454BFA86BD/Library/Application Support/com.apple.watchconnectivity/26972EDE-BA7C-4E60-8DCD-23190DC18928/FileTransfers/1D0BB287-F528-4020-A246-C0FE91A43FB9/file-transfer-result

The Simulator doesn't support transferFile, so any error that comes from attempting to call it on a WCSession can be ignored whilst developing with the Simulator.

I know it seems cumbersome, but I do wrap my transferFile stuff in a compiler conditional so it doesn't attempt to send files if the target is the Simulator, and you don't see the errors. You could have just one instance of the transferFile method in a shared functions file so the conditional only has to be in that one file?

func sendFile(_ file: String) {
#if targetEnvironment(simulator)
    session.transferFile() etc.
#endif
}

// Somewhere else where you need to send a file
sendFile(myFile)

You can get stuck down a massive rabbit hole trying to correct errors you'll likely never actually see.

I'd keep coding as though the file has been transferred across, and write code that handles receiving the file on the Watch, then deploy to an actual device to test it. I recently spent weeks updating my app for iOS 16 before I took the plunge and deployed to my only iPhone and Watch.

Thank you @darkpaw!
Your error is different than WCErrorCodeFileAccessDenied, so at least I know that there might be a different issue in my code. Thanks so much.

I'd keep coding as though the file has been transferred across

You're right, but I'd also have to implement something in compiler conditionals on the watch side, otherwise I'll never be able to check the functionality after transferring the file...

  • If you're only sending files from the iOS app to the Watch app you'll only have the conditional check in the iOS app to stop you sending files if you're in the Simulator.

    The Watch app would never hit the func session(_ session: WCSession, didReceive file: WCSessionFile) method if you're using the Simulator.

    If you're sending files both ways, then yes you'd need a conditional in both targets.

Add a Comment