Add a local swift package in swift project in Xcode 13 - swift

I want to add a swift package in my project. It appear in packages folder (by a drag n drop) but my project doesn't see it with "import myPackage", I've no such module error

1) Go to you project target -> general -> Frameworks, Libraries, and Embedded content
2) add package with + button. ( I only added testFramework on picture below just for example)

Use .package(path:) description in Package.swift.
You can add a dependency to a package located at the given path. And you can edit the package when debugging.
As PackageDescription mentioned this description:
The Swift Package Manager uses the package dependency as-is and does not perform any source control access. Local package dependencies are especially useful during the development of a new package or when working on multiple tightly coupled packages.

Related

Xcode import local Swift Package and build from the app

The goal is to import a local Swift Package "Shared" into a Xcode project and have them both in a workspace.
I have created a workspace, dragged and dropped both the package and the project in, and then added the package to the app by adding it to Frameworks, Libraries, and Embedded Content.
This works when building from the workspace! But I have to make it also possible to build from the app project, currently it throws: "Missing package product 'Shared'".
I know it is possible to do what I want because I have an example project where it works, in there Shared is listed as a local Swift Package in the app project, in mine it is not. In the project Shared is listed under Frameworks, Libraries, and Embedded Content but can't be added again after removing the reference.
It would be great if someone could help me with this!
The solution is to create a local Swift Package in the app project and to import the Shared Package there. Then it will be available in the whole project.

Add a local Swift Package target to an existing Xcode project

I have an existing Xcode project that contains targets for a "traditional" iOS app ("Foo") and an iOS framework ("FooLib"). When the Xcode 12 beta dropped a few days ago, I added a multiplatform (iOS/macOS) SwiftUI app target ("Foo SwiftUI") to the same project. Now I want to make my framework cross-platform, too, so I added a multiplatform Swift Package ("Foo Package") to the project and moved the iOS framework classes to the new Swift package. I then added this package to all app targets' Frameworks, Libraries, and Embedded Content sections. It appeared to work for all app targets until I cleaned the project and tried again. Now the app targets complain that the Foo Package can't be resolved:
Missing package project 'FooLib'.
I tried removing & re-adding the FooLib package to the app targets, but it no longer shows up in the pop-up list of frameworks and libraries to add. Are local Swift packages explicitly unsupported in Xcode projects? Do I need to put the package in its own Git repo and set it up like any other third-party package dependency?
What I'm most confused about it that it looks like it worked right after I created the Swift package, but not after I cleaned the project and tried re-running the app targets.
OK, sorry for my previous answer. — It is obvious how to share a package with yourself by way of a remote URL, such as GitHub, that serves it. Basically you are playing the role of both developer and end-user, and it's clear how to do that. So I think what's needed here is a step-by-step tutorial to sharing a package with yourself locally without actually serving it.
In Xcode, choose File > New > Swift Package and save as MyLibrary to the Desktop.
Now choose File > New > Project, choose the iOS App template, and save as App1 to the Desktop.
You now have two windows open. Drag MyLibrary from the project navigator in the MyLibrary window into the empty area at the bottom of the project navigator in the App1 window.
Quit Xcode.
Launch Xcode again and open App1. Look, the MyLibrary icon now has hierarchical contents. Edit the app target and add MyLibrary library as a dependency.
You can now edit MyLibrary; you can also import MyLibrary in your code and you will be able to use any public members of public types.
Close App1 and create another project, App2. Repeat steps 3, 4, 5, and 6.
From now on, either App1 and App2 can "see" MyLibrary. From either one, you can edit MyLibrary, you can import it and use its code. But you cannot have both App1 and App2 open at the same time. If you do, one of them will complain that the package is missing. So you'll be fine as long as you only have one at a time open.
Now, if you want to escape that limitation, then go back to the first way of dealing with all this: upload the package to GitHub and acquire it in your projects as a package dependency.
For me, it works using Xcode Workspaces “around” local Projects and Swift Packages.
Create App project
Create Swift Package
Create Workspace for app project
Add the App project to the Workspace
Add the Swift Package to the Workspace, too
In the app target “General” settings, “embed&sign” the Swift Package from the current workspace
You might have to restart Xcode afterwards for it to pick up on the changes ...

UI Test target does not recognize Swift package from custom framework in xcworkspace

I am developing several projects in a single workspace (monorepo). The workspace contains a shared framework that contains code shared between the projects. Some of the code depends on external packages that I import using the Swift Package Manager. Everything is working except that the packages aren't recognized when I use the UI testing target. When I run the UI tests for one of the projects it complains that the packages cannot be found (in the framework). Another solution that suits my needs is also welcome. Anyway, I'm using Xcode 11.3. To reproduce:
Create a new workspace.
Add a new project A and a new framework B into the workspace.
Add any dependency (for example SDWebImage) to the framework.
Add a Swift-file to the framework that just does import SDWebImage.
Now add framework B as a dependency to project A.
If you build project A or unit test project A, there is no problem. However, when you run UI tests on project A it complains that it cannot find the module SDWebImage in the Swift-file you added in point 4 above. Any idea how to solve this?
Edit: When I use Cocoapods instead it gives me the same error. When I use use_frameworks! it doesn't give me the error, but it crashes with "SDWebImage: image not found".
You have to manually add your B framework as a linked library in on your UI Tests target under Build Phases -> Link Binary With Libraries

How to update Swift dependencies in Xcode

After I create a new swift package with dependencies I call swift package generate-xcodeproj. If my dependencies have a new version I call swift package update. The new version of my dependency gets downloaded and built but Xcode now has a bad reference to the old version of the dependency. I can call swift package generate-xcodeproj again but this will remove any custom targets I have setup.
How do I update my swift dependencies and my Xcode project without deleting my custom targets?
I just stumbled upon this question and found that the solution to "How to update swift dependencies in Xcode" has probably changed now that Swift Packages have been around for a few years.
For me, the solutions was to simply go to File -> Swift Packages -> Update to Latest Package Versions.
Many of the problems with packages not updating are because the swift package version rules limit the automatic package updates to the current major version only, i.e v3.3.1 of a package will update to v3.4.0, but will not update automatically to v4.0.1. Therefore using the update options in Xcode does not necessarily get the latest major version of a package.
To resolve, Open the project from the project panel, select the project (not the targets), then select the "Swift Packages" tab. Double click on the package you want to update and change the minimum version to the next major version.
- Update a single dependency using Xcode
This method will save a lot of resources and time. Because it won't force other packages to redownload.
Double click on the package in the tab you mentioned and change the version to anything else. It will then recheck the remote repo. The benefit of doing this is to only update the selected package. (Also, it's better to have the current using version be set in the package.)
- Update ALL dependencies using Xcode
From File -> Swift Packages -> Update to Latest Package Versions
🤨 Single package with GUI (Xcode 12 and above)
Right-click on the package from the left navigation pan and select Update Package
note that you will see Xcode saying update all packages but it will update only the selected one
Instead of trying to preserve your changes to generated project, you can manage dependencies in a separate project, like CocoaPods does.
When starting new project:
create Xcode project for your app MyApp.xcodeproj
save as a workspace MyApp.xcworkspace
create package for your dependencies
mkdir MyDeps && cd MyDeps
swift package init --type library
add dependencies to Package.swift
generate Xcode project for the dependencies package
swift package generate-xcodeproj
add generated project MyDeps.xcodeproj to your workspace MyApp.xcworkspace
add target MyDeps.framework to Linked Frameworks of your app MyApp.xcodeproj
With this setup you can freely update dependencies in Package.swift and regenerate dependent project as needed.
I had an issue with CryptoSwift using Xcode 12.5. My version was 1.3.1 and the issue was fixed in 1.4.0.
I tried :
updating by File -> Swift Packages -> Update to Latest Package Versions.
xcodebuild -resolvePackageDependencies
But both did not work.
I manually went and changed target -> Swift packages -> Version rules
and Xcode automatically installed the newer version and I was out of my error.
If the library is used by a particular target, the library won't be updated to the latest version, at least in my case (Xcode 14.2).
I was using OneSignal which requires to add a target (OneSignalNotificationServiceExtension) which depends on the OneSignal library in the "Frameworks and libraries".
So:
remove the required lib voice from the dependency in the extension,
update the library with right click -> "update package"
re-add to the extension the updated library in the "Frameworks and libraries"
Screenshot of which row to delete to let the library update properly (remember to read later).

Add reference to same Nuget package but for different targets

I have a solution in Visual Studio 2013 with more C# project files that have source code in common but are targeting for different platforms (.Net, WinRT, .Net Micro Framework and so on).
All the csproj files are under the same directory.
These projects use a Nuget package that is available for all the above platforms itself.
If I add this Nuget package for one of the project (ex. .Net), the package.config file is created and inside has reference to that target (ex. .Net). The package is downloaded in the packages folder.
If I try to add the same package but for a different target to another project in the solution, the UI tells me that the package is already installed. It's true because a package.config file is already there but I'd like to have the same package for a different target.
So my question is the following : how can I add the same Nuget package to all different projects but with different targets ?
Thanks,
Paolo
Unfortunately, I don't think NuGet supports your scenario.
NuGet expects the packages.config file to be in the same folder as the .csproj file. There should be a 1-to-1 relation between these files. You should create a separate folder for each project rather than keep all .csproj files in the same folder.
If you want to share code across multiple projects, the easiest way is to use the new Shared Project support in Visual Studio. Normally this only applies to Universal Projects, but there is an extension[1] that you can install that enables Shared Projects for all project types.
Simply create a new Shared Project. Add all you common code to it. Then in your platform specific projects, you can simply Add Shared Project Reference.
Since each project is now independent, NuGet will add the appropriate package.
Hope this helps. Good luck!
[1] Shared Project Reference Manager https://visualstudiogallery.msdn.microsoft.com/315c13a7-2787-4f57-bdf7-adae6ed54450