Is it possible to use an iOS Xcode project as a dependency in a Swift package?

I want to be able to keep both my code and the test code in the same repository. This code is being used as a framework/dependency in a Swift package. Ideally, I would create an iOS project (this is UI code being written and in order to ensure it works needs to be tested on an actual device / the simulator), add the UI code in there and be able to import that project into a Swift package. But when I add the project repository as a dependency obviously it complains about the missing Package.swift file and won't work.

Is there a way to get this so that it's all in just one module? I don't want to pollute my workspace with modules of the type (Swift Package) Tests (the iOS Xcode project for testing the Swift Package).

In short: You can't

What you can do is exclude the Xcodeproj files from your library package.

targets: [
    // Targets are the basic building blocks of a package. A target can define a module or a test suite.
    // Targets can depend on other targets in this package, and on products in packages which this package depends on.
    .target(
      name: "LibraryName",
      dependencies: [...],
      exclude: [path_to_xcode_project]
    ),
...

This is how you can add example projects to your package

1 Like

So what you're suggesting is to create a Swift package and then an Xcode package inside of it? Why is the exclusion necessary?

From what I understand, you have 3 "projects":

package or Xcode project/workspace A that depends on swift package B which has some code that you want to test in in an Xcode project (C)

so A depends on B which is not dependent on C but C is used to test the code on device

C can't be part of the source of swift package B. so you "exclude" it, even though it exists just for testing. Even though exclusion will still make those files visible to project A, just that they won't be compiled

what stops you from using the test target of the swift package to test your ui code though?

Need to run the test code on an actual device/simulator. As far as I know you can't do that in a vanilla Swift package. For example, if it's a custom UIView it would likely be placed as the sole view in an empty app's root view and be tested in isolation.

For example, it may be a view that supports some sort of custom gesture that would need to be tested in hand.

Yeah, see this is a similar problem to what I faced in the past. I tried your approach, then tried to drag and drop the Swift package to an existing workspace and it's not registering as a Swift package. The problem with this is I want to have it be a submodule in my project Z — which depends on project A — so I can edit the source code in one main repo. The issue with this is that because project B is a dependency of project A, it is pulled from the repo by Xcode. But I want to be able to edit it locally.

Normally, I can just drag and drop the repo with the same name and Xcode will discard the fetched repository and use the local one. But because it's not recognizing it as a Swift package it's not disregarding the fetched repo, so any local changes I make to it have no effect on the build.

I think what you're trying to do is no different from what others are doing when they still support cocoa pods or provide an Xcode project as example.
I suggest you have a look at the github repos of popular libraries like Alamofire, Realm Swift etc. You'll see an xcworkspace or xcproject in the repo. Open it and see how they referenced the files in the containing package to be compiled as if they were part of the project but then exclude the Xcode related stuff in the package.swift like I was saying before. this way you can edit the files both in the test Xcode project and the swift package and you can have everything in one repo

There's another thing that might trip you over - a bug in Xcode where dragging a swift package folder makes a folder reference instead of a package reference not recognising that it's a swift package sometimes. There are various ways to fix this but from my experience deleting derived data fixes it