1

I'm having trouble converting my app from WatchOS 1 to WatchOS2. I'm programmatically creating a sequence of images on the iPhone for the Watch to play.

I'm putting them in a zip file (using SSZipArchive) in iOS and using transferFile() to send it over to the watch where I unzip it in the Watch Extension delegate to the shared container between the Watch Extension and Watch App, that the Watch App can play the sequence later:

func session(session: WCSession, didReceiveFile file: WCSessionFile) 
{
    imagesURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.com.xxxx.images")

    SSZipArchive.unzipFileAtPath(file.fileURL.path, toDestination:imagesURL!.path)
}

I've checked that the shared group is set up correctly, and I can see the image files in the shared directory (imagesURL!.path).

But when I get ready to play the sequence with:

image.setImageNamed("myImages") // myImages0.png, myImages1.png, myImages2.png, etc.

I get the error: Unable to find image named "myImages" on watch

  • Am I putting the images in the right place?
  • Am I referring to them correctly in setImageNamed?
  • Am I missing something else?
ScottyB
  • 2,167
  • 1
  • 30
  • 46

2 Answers2

1

Why setImageNamed: fails

According to the WKInterfaceImage documentation, setImageNamed loads the image from the watch app bundle.

Whenever possible, place image resources in an asset catalog in your Watch app bundle (not in your WatchKit extension’s bundle). Placing them in the Watch app bundle lets you use the setImageNamed: method to load the animated image at runtime, which simplifies the loading process.

To load an animated image sequence from images in your Watch app bundle, you must name your image resources appropriately and use the setImageNamed: method of this class.

This is why setImageNamed: can't find the images, as they are not a static resource bundled with the watch app.

How to load a dynamic animated image

Since your animation images are dynamic, this is handled by the watch app extension.

For animations you generate dynamically, use the animatedImageWithImages:duration: method of UIImage to assemble your animation in your WatchKit extension, and then set that animation using the setImage: method.

You need to first use animatedImageWithImages:duration: to assemble the dynamic animated image you transferred, then set that animation using setImage:

let animatedImages = UIImage.animatedImageWithImages(images, duration: 3)
image.setImage(animatedImages)

Update:

As Scotty pointed out, the better solution is to use animatedImageNamed:duration: to avoid needing to create the array of images!

Community
  • 1
  • 1
  • Thanks for sending me in the right direction. However, I realized that what I should be doing is creating the animated UIImage on the phone, then sending that over directly (for example: http://stackoverflow.com/questions/29515599/how-to-pass-uiimage-from-iphone-app-to-apple-watch-app). I was incorrectly trying to keep using the old Watch OS 1 approach with image files. That explains why no one (except me) is talking about using image files for animation with Watch OS 2! In fact, I imagine this is talked about in Apple's Watch OS 2 conversion guide which seems to be no longer available online. – ScottyB Jul 02 '16 at 14:54
1

The correct answer is to use the animatedImageNamed:duration: method of UIImage if you have a series of image files already created, then set that animation using the setImage: method.

So the correction to my original code is a simple one-line change:

image.setImage( UIImage.animatedImageNamed("myImages", 3) ) // myImages0.png, myImages1.png, myImages2.png, etc.

(assuming the duration is 3 seconds)

ScottyB
  • 2,167
  • 1
  • 30
  • 46