Within the earlier tutorial, we created an animated menu bar in SwiftUI. What if you wish to reuse the code in different tasks? After all, you’ll be able to copy & paste the code from one mission to a different however there’s a higher approach to reuse the code through the use of Swift Package deal.
Swift packages are reusable parts that builders can import of their tasks. With Swift Package deal Supervisor, the built-in device for creating and managing Swift packages, you’ll be able to simply share reusable code within the type of Swift packages.
On this tutorial, I’ll stroll you thru the method of making Swift packages and present you how one can flip the code of the animated menu bar right into a reusable SwiftUI part.
Please be aware that I exploit Xcode 13 to create the demo code. Nevertheless, it’s best to have the ability to observe procedures even in case you are utilizing a decrease model of Xcode.
Creating Swift Packages
There are two methods to create a Swift package deal. You possibly can both use command line or Xcode.
Utilizing Command Line
To create a Swift package deal utilizing command line, open Terminal and key within the following instructions:
mkdir AnimatedMenuBar cd AnimatedMenuBar swift package deal init |
The folder title is the package deal title. Right here, we use the title AnimatedMenuBar. When you hit the return key, you will notice the next messages:
Creating library package deal: AnimatedMenuBar Creating Package deal.swift Creating README.md Creating .gitignore Creating Sources/ Creating Sources/AnimatedMenuBar/AnimatedMenuBar.swift Creating Exams/ Creating Exams/AnimatedMenuBarTests/ Creating Exams/AnimatedMenuBarTests/AnimatedMenuBarTests.swift |
This generates the fundamental skeleton of the Swift package deal together with the supply and checks. You possibly can additional edit README.md file to offer an outline of the package deal. Package deal.swift
is the manifest file which defines the package deal’s title and its contents utilizing the PackageDescription
module.
import PackageDescription
let package deal = Package deal(
title: “AnimatedMenuBar”,
merchandise: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: “AnimatedMenuBar”,
targets: [“AnimatedMenuBar”]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: “1.0.0”),
],
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 this package depends on.
.target(
name: “AnimatedMenuBar”,
dependencies: []),
.testTarget(
title: “AnimatedMenuBarTests”,
dependencies: [“AnimatedMenuBar”]),
]
)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// swift-tools-version:5.3 // The swift-tools-version declares the minimal model of Swift required to construct this package deal.
import PackageDescription
let package deal = Package deal( title: “AnimatedMenuBar”, merchandise: [ // Products define the executables and libraries a package produces, and make them visible to other packages. .library( name: “AnimatedMenuBar”, targets: [“AnimatedMenuBar”]), ], dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: “1.0.0”), ], 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 this package depends on. .target( name: “AnimatedMenuBar”, dependencies: []), .testTarget( title: “AnimatedMenuBarTests”, dependencies: [“AnimatedMenuBar”]), ] ) |
Be aware that the package deal manifest should start with the string // swift-tools-version:
, adopted by a model quantity reminiscent of // swift-tools-version:5.3
.
Utilizing Xcode
When you desire to make use of Xcode to create the package deal, you’ll be able to select File > New > Mission… and choose Swift Package deal underneath Multiplatform.
Updating the Supply
The AnimatedMenuBar.swift
file underneath the Sources
folder solely comprises the default content material generated by Xcode:
public init() {
}
}
public struct AnimatedMenuBar { public non-public(set) var textual content = “Hey, World!”
public init() { } } |
It’s a must to replace the file with the code for creating the animated menu bar. On this case, we reuse the code that we have now walked you thru within the earlier tutorial.
@out there(iOS 14, macOS 11.0, *)
public struct AnimatedMenuBar: View {
@Binding var selectedIndex: Int
@Namespace non-public var menuItemTransition
var menuItems = [ “Travel”, “Nature”, “Architecture” ]
public init(selectedIndex: Binding<Int>, menuItems: [String] = [ “Travel”, “Nature”, “Architecture” ]) {
self._selectedIndex = selectedIndex
self.menuItems = menuItems
}
public var physique: some View {
HStack {
Spacer()
ForEach(menuItems.indices) { index in
if index == selectedIndex {
Textual content(menuItems[index])
.padding(.horizontal)
.padding(.vertical, 4)
.background(Capsule().foregroundColor(Coloration.purple))
.foregroundColor(.white)
.matchedGeometryEffect(id: “menuItem”, in: menuItemTransition)
} else {
Textual content(menuItems[index])
.padding(.horizontal)
.padding(.vertical, 4)
.background(Capsule().foregroundColor(Coloration( crimson: 244, inexperienced: 244, blue: 244)))
.onTapGesture {
selectedIndex = index
}
}
Spacer()
}
}
.body(minWidth: 0, maxWidth: .infinity)
.padding()
.animation(.easeInOut, worth: selectedIndex)
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
import SwiftUI
@out there(iOS 14, macOS 11.0, *) public struct AnimatedMenuBar: View { @Binding var selectedIndex: Int @Namespace non-public var menuItemTransition
var menuItems = [ “Travel”, “Nature”, “Architecture” ]
public init(selectedIndex: Binding<Int>, menuItems: [String] = [ “Travel”, “Nature”, “Architecture” ]) { self._selectedIndex = selectedIndex self.menuItems = menuItems }
public var physique: some View {
HStack { Spacer()
ForEach(menuItems.indices) { index in
if index == selectedIndex { Textual content(menuItems[index]) .padding(.horizontal) .padding(.vertical, 4) .background(Capsule().foregroundColor(Coloration.purple)) .foregroundColor(.white) .matchedGeometryEffect(id: “menuItem”, in: menuItemTransition) } else { Textual content(menuItems[index]) .padding(.horizontal) .padding(.vertical, 4) .background(Capsule().foregroundColor(Coloration( crimson: 244, inexperienced: 244, blue: 244))) .onTapGesture { selectedIndex = index } }
Spacer() }
} .body(minWidth: 0, maxWidth: .infinity) .padding() .animation(.easeInOut, worth: selectedIndex)
} } |
For Swift package deal, the AnimatedMenuBar
struct is required to set to public
. And we have to create a customized init
with public entry degree.
Besides that, the remainder of the code is nearly the identical. Chances are you’ll discover one other distinction that we use the @out there
attribute to annotate the struct with availability data. The road of code signifies that the struct is barely out there for iOS 14 and macOS 11.0 (or later).
Modifying Take a look at Code
By default, Xcode generates a check folder so that you can embody automated checks. You possibly can modify the generated file named AnimatedMenuBarTests.swift
to incorporate your check code. Nevertheless, for this demo, we aren’t going to write down the code. You possibly can simply remark out the next line of code:
// XCTAssertEqual(AnimatedMenuBar().textual content, “Hey, World!”) |
Including Dependencies (Elective)
Although this package deal doesn’t rely on different Swift packages, you’ll be able to edit the dependencies
part to incorporate your dependent packages for those who want:
dependencies: [ .package(url: “https://url/to/dependency”, from: 1.0.0) ], |
Including Supported Platforms
Whereas Swift packages are supposed to offer multiplatform assist, you need to use the platforms
attribute in Package deal.swift
if the package deal solely helps a sure platform. Right here is an instance:
platforms: [ .iOS(.v14), .macOS(.v11) ], |
For this demo package deal, it’s out there for iOS 14 and macOS 11.0 (or later).
Publishing the Package deal on GitHub
After you made all of the adjustments, it’s best to have the ability to construct your package deal to make use of it regionally. To additional share the package deal with builders in your group or neighborhood, you’ll be able to publish the package deal on GitHub.
Go as much as the Xcode menu and select Supply Management > New Git Repositories… to create a brand new respository.
Subsequent, swap over to the Supply Management Navigator. Proper click on Remotes and select New “AnimatedMenuBar ” Distant…
Assuming you’ve already configured your GitHub account in Xcode, it’s best to have the ability to create a distant repository. Set the repository title to AnimatedMenuBar and key in your description of the package deal. Relying in your choice, you may make the package deal out there to public or simply hold it to your individual mission. For this demo, I set it to public.
When you hit the Create button, Xcode will create the repository on GitHub and add the native recordsdata to the repository.
At present, the package deal is just not assigned with a model quantity. To set a model for the package deal, go to the Supply Management Navigator. Proper click on the entry of the preliminary commit and select Tag.
Subsequent, set the tag to 1.0.0
and click on Create to verify the change.
The change you simply made is barely out there regionally. To set the tag on the distant repository, you’ll want to push the adjustments. Go as much as the Xcode menu, select Supply Management > Push. Please be sure to tick the Embrace tags checkbox earlier than hitting the Push button.
That’s it! You’ve efficiently revealed the Swift package deal onto GitHub. And, it’s accessible through https://github.com/appcoda/AnimatedMenuBar.
Utilizing Swift Package deal
To make use of the Swift package deal in any Xcode mission, select File > Add Package deal… and key within the package deal URL within the search bar.
Xcode ought to then present you the package deal description and model. Click on Add Package deal to obtain and add the package deal to your mission.
As soon as the package deal is downloaded, it’s best to see the package deal underneath Package deal Dependencies within the mission navigator. Now you might be prepared to make use of the AnimatedMenuBar
view within the mission.
All you’ll want to do is import
the AnimatedMenuBar package deal and use the AnimatedMenuBar
view like this:
struct ContentView: View {
@State var tabIndex = 0
var physique: some View {
AnimatedMenuBar(selectedIndex: $tabIndex)
}
}
import SwiftUI import AnimatedMenuBar
struct ContentView: View { @State var tabIndex = 0
var physique: some View { AnimatedMenuBar(selectedIndex: $tabIndex) } } |
Abstract
On this tutorial, I’ve walked you thru the steps to create a Swift package deal for reusing some frequent SwiftUI views. The approach shouldn’t be restricted to the reuse of SwiftUI views. You possibly can apply it to frequent parts that may be shared between groups and tasks.
What do you consider Swift packages? Have you ever used Swift Package deal Supervisor to create shareable parts? Please depart me remark and let me know.