Add Playground to Swift Package - WWDC20 10096

In the WWDC session Explore Packages and Projects with Xcode Playgrounds. The demo showed a playground NutritionFacts inside of a package. I tried to create a playground inside my package and the playground cannot find my module. What setup needs to occur to allow the playground to be able to use the module besides typing

import module

Replies

Same problem here - I've tried using a playground inside one of my Swift package's dependencies and creating a Playground for my own Package - both compile fine, I can import my package module and auto-complete works ok but it crashes when it runs with a "Couldn't lookup symbols" error.
I’ve had a number of issues with playgrounds and swift packages, possibly related to having a C package somewhere in the dependency chain (apple if you’re reading this there’s a sample project on FB7859836.

Although some of my issues are documented more fully there, here are some “tips and tricks” I’ve learned the hard way:
  • Sometimes it helps to clean and build the package (in Xcode, not on CLI) for the same platform as the playground. For iOS playgrounds this is Simulator. Note that Xcode likes to change the active platform on me randomly, complicating maintaining this.

  • Related, I think sometimes an out-of-date binary gets picked up, which may have unexpected runtime or build time results.

  • importing inside the playground module (that is, inside a file in Sources) doesn’t work for me at all, whereas importing on the playground page itself works better. This does complicate authoring playground code for re-use.

  • Sometimes it helps to build the playground multiple times, like at least 5 times. Doing the same thing can produce different results!

  • Sometimes Issues displayed somewhere in the GUI (issue navigator, source editor, or even the bottom drawer) are alternate worlds that disagree with one another. Therefore if your workflow depends on looking in a consistent location (e.g., issue navigator) and expecting issues to disappear once fixed, you might incorrectly conclude that the import error isn’t fixed by your changes, when in fact the situation changed some other place in Xcode

Short answer:

Your Package needs to be part of a Project (or Workspace) for a Playground inside of your Package to be able to find any public structs/classes that your Package provides.

Longer answer:

The Fruta demo that's mentioned in WWDC 10096 has the NutritionFacts Package added to the Fruta Project already. This means that the person who set up the Fruta Project dragged and dropped the NutritionFacts Package into the Fruta Project, causing Xcode to automagically set up a Target for the Package, and the dev then added the Package to all of the existing Targets in the Project (added NutritionFacts Package to "General -> Frameworks and Libraries [and Embedded Content]" for each existing Target).

You can test this yourself by creating a test Package on the command line/in Xcode, then dragging/dropping it from Finder into a test Project; Xcode will quietly and in the background create a new build target for the Package that you just imported, but you'll still need to add the Package by hand to the main Target in your test Project.

To run the NutritionFacts Playground that has been added to the Fruta Project, you will need to build the NutritionFacts Target (select NutritionFacts Target, then hit "Product -> Build" or "⌘-B") before you try to run the NutritionFacts Playground, or you will see errors about "cannot find NutritionFact in scope" when you first try to run the Playground.

A few extra things:

  1. You may already have done this, but for people new to Swift/Packages/Playgrounds, the structs/classes in your Package that you want to use in a Project or Playground need to be marked public. This includes having a default public init() initializer for structs in your Package, because Xcode doesn't create these by default.
  2. The Fruta project currently (July 2021) on Apple's website is for Xcode 13. You'll have to use some kind of mirror (perhaps "web dot archive dot org") to download older copies of the Fruta Project if you're still running Xcode 12. Going back to say November 2020 or so should get you the version of the Fruta Project for Xcode 12.

I take back my previous answer.

It is possible to add a Playground to a Swift Package.

Open your Swift Package in Xcode, add an iOS/macOS/tvOS Playground, and add your code to the Playground.

Click on the Playground in the Project navigator, and in the File Inspector, make sure you have "Build Active Scheme" checked, then run your Playground. Everything then "Should Just Work".

You can even change the Playground Platform in File Inspector, stop the Playground and rerun, and it should rebuild your Package and rerun your Playground with the new Platform setting.

It may take Xcode a few seconds to figure out that your Package has been built for the target Platform before the "Module 'PackageName' was created for incompatible target" error goes away.